home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Gold Collection
/
Software Vault - The Gold Collection (American Databankers) (1993).ISO
/
cdr22
/
bytewb.zip
/
BYTEWB.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1993-06-24
|
118KB
|
4,049 lines
{**********************************}
{ BYTE Windows Benchmarks }
{ Version 1.0 }
{ July 1992 }
{ Turbo Pascal Version by }
{ Rick Grehan }
{ Version 1.1 Revisions by }
{ Raymond GA Cote }
{ Appropriate Solutions, Inc. }
{**********************************}
{ HISTORY:
93Jan27 RGAC -- Appropriate Solutions, Inc.
Added following changes culminating on this date.
1: -L on command line will cause tests to be run automatically,
sent to a log file, and program to terminate.
2: a filename on the command line will be used for logfile, otherwise
we will use a default name.
3: Window is now set to 640 by 480.
4: Did not change algorithm in sequential file I/O. Simply limited
writing within array bounds and started/stopped timer.
5: Since sfio was setup as a single reportable number I left it that way.
6: System no longer appears to be crashing. I've run it several hours
without problems. It still needs, however, error checking and
handling routines.
7: Sfile_io test was not set-up as a timed test. Rather it runs once
and one-time experiment is used for a timing value. I did not change this.
8: Rfile_io is configured as a timed test. However, I did not alter
the user interface to allow timing data to be entered.
However, I do use the global variables for timing the test.
9: Random file i/o routine was translated from Byte Low level Benchmarks.
It uses a single-character array (it is never changed).
This may cause problems with upcoming intelligent cache controllers
which may not decide to actually write the information.
Needs to be changed in future software release.
10: Lab needs to determine test environment for running windows benchmark.
SmartDrive sizes, etc.
11: Random I/O currently set to run for 30 seconds. This produces 965 Kbytes/second on
my system which is just slightly slower than the BBENCH low-level throughput value.
The following values were received from the test at varying times:
15s 1,421 Kbytes/sec
30s 965 Kbytes/sec
45s 728 Kbytes/sec
60s 610 Kbytes/sec
Current interface does not allow time to be set from this user interface.
12: Added a 5-second delay to start of random file i/o test. My reasoning is as follows:
Random file i/o runs immediately after the sequential file i/o. System may still be
flushing the cache from the sequential test. This will have a dramatic impact on the
test results.
Specifically. Running the random test by itself will produce different results than whe
they are run in a batch.
13: Log file is timestamped and contains its own name.
14: Local Memory test no longer locks up the system.
15: Put local memory test into iteration loop. Did quick check to see that it performed
properly. Verified that calcluated output shown in reports is valid.
16: Put global memory test into iteration loop. Reported numbers are very low.
Test slows down dramatically between iterations. First iteration takes 1.4
seconds, last iteration takes 6.2 seconds.
I've not explored the problem.
17: Fixed improper addition (or nonaddition) of '0' to minutes in timelog.
18: Instead of handling display of external log files, I've allowed you to view
results of all tests up to this point. Viewing also logs all test results
to the log file.
19: Changed displayBenchLine so it tracks its own position.
Added InitBenchDisplay which sets-up the variables.
Should be called before each new set of screen displays.
Note: you won't get scrolling with these routines.
20: Allow user to enter name of logfile. Currently only accepts
eight character name and three-character extension. No error checking
done in current code. Caveat Emptor.
============= that's it for now, I'll come back and polish a few
things in about a week. ==
}
{
Things that still need doing:
1: File I/O error handling.
2: Memory allocation error handling.
3: User interface is much too "cute".
4: Need to follow Windows GUI standards.
5: Still need processor identification.
7: Display system configuration.
10: Final testing.
11: Validation from the field.
13: Determine if global memory test is functioning properly.
14: Determine when window is activated and update the information.
15: Need to not use the Microsoft trademark as minimized icon.
}
program ByteWbench;
{$R BYTEWB } { Our resource file is BYTEWB.RES }
{$X+ } { Enable extended syntax }
uses WinTypes, WinProcs, Strings, WinDos;
(**********************
** GLOBAL CONSTANTS **
**********************)
CONST
NULL = 0;
ID_PIXEL_BUTTON = 101;
ID_LINES_BUTTON = 102;
ID_RECTS_BUTTON = 103;
ID_POLYS_BUTTON = 104;
ID_ARCE_BUTTON = 105;
ID_BITBLT_BUTTON = 106;
ID_LMEM_BUTTON = 107;
ID_GMEM_BUTTON = 108;
ID_SFIO_BUTTON = 109;
ID_RFIO_BUTTON = 110;
ID_TEXT_BUTTON = 111;
ID_PIXEL_SECS = 120;
ID_LINE_SECS = 121;
ID_RECT_SECS = 122;
ID_POLY_SECS = 123;
ID_ARCE_SECS = 124;
ID_BITBLT_SECS = 125;
ID_LMEM_SECS = 126;
ID_GMEM_SECS = 127;
ID_TEXT_SECS = 128;
IDM_SETLOG = 201;
IDM_DISPLOG = 202;
IDM_EXIT = 203;
IDM_INFO = 204;
IDM_COMPINFO = 205;
IDM_CONFBENCHES = 211;
IDM_SYSCONF = 212;
IDM_SETDEFS = 213;
IDM_EXECUTE = 221;
IDB_OK = 150;
IDB_CANCEL = 151;
IDL_OK = 101;
IDL_CANCEL = 103;
IDL_LOGFIELD = 102;
(**
** Number of timer array elements.
**)
time_array_elems = 4;
(**
** Minimum number of seconds for tests.
** These define the minimum that the user can set a test
** to, the idea being that anything less makes the results
** questionable.
*)
min_pixel_secs = 30;
min_line_secs = 30;
min_rect_secs = 30;
min_poly_secs = 30;
min_arce_secs = 30;
min_bitblt_secs = 30;
min_lmem_secs = 30;
min_gmem_secs = 30;
min_text_secs = 30;
min_rfile_io_secs = 30;
min_sfile_io_secs = 30;
(**
** These constants set the number of "things done" per
** iteration. In a future version, it might be a good
** idea to have these fellows become minimum values and
** let the user adjust the number of repetitions per
** iteration.
*)
pixels_per_iter =1000; { # of pixels per iteration }
lines_per_iter = 1000; { # of lines per iteration }
polys_per_iter = 20; { # of poly lines per iteration }
rects_per_iter = 1000; { # of rects per iteration }
ellps_per_iter = 1000; { # of ellipses per iteration }
bmap_points = 1000; { # of bitmap points per iteration }
lmems_per_iter = 1; { # of local memory tests per iter }
gmems_per_iter = 1; { # of global memory tests per iter }
text_per_iter = 400; { # of text strings per iteration }
{ the following bizarre value comes from the use of a nonBinary-power
value as the upper bounds of the sequential I/O test. I've left
it here since that is how the code was presented. rgac }
sfio_bytes_per_iter = 19995904 * 2; {same # bytes for write and read}
disk_space_needed = 6000 * 1024; { 6 MB }
bmap_size = 72; { Bitmap x & y dimension }
(*
** NOTE: The pre-release version of the benchmarks used
** pen styles other than the ps_Solid. This caused problems
** with some accelerator cards, which had a hard time doing
** ps_Dash and ps_Dot pens. The results were skewed [how
** many times have you seen dashed or dotted lines onscreen?].
** So, all pens are now ps_Solid. --RG
*)
pen_style: ARRAY [0..2] OF Integer =
( ps_Solid, ps_Dash, ps_Dot );
(**
** Brush types.
** NOTE: The benchmarks have a larger number of null brushes so
** that they tend to test empy polygons more frequently than
** filled ones. The actual ratio should -- at some time in
** the future -- be determined by profiling.
**)
brush_style: ARRAY [0..9] OF Integer =
( Black_Brush, Null_Brush, DkGray_Brush, Null_Brush,
Gray_Brush, Hollow_Brush,
LtGray_Brush, Null_Brush, White_Brush, Null_Brush );
(**
** The following array of edit box id numbers are used
** to facilitate the scanning of edit boxes on the
** configuration scree.
**)
edit_box_ids: ARRAY[0..8] OF Word =
( ID_PIXEL_SECS, ID_LINE_SECS, ID_RECT_SECS,
ID_POLY_SECS, ID_ARCE_SECS, ID_BITBLT_SECS,
ID_LMEM_SECS, ID_GMEM_SECS, ID_TEXT_SECS );
(**
** The following array is used to scan edit boxes
** and verify that their contents are above the
** allowed minimum.
**)
edit_box_mins: ARRAY[0..8] OF Word =
( min_pixel_secs, min_line_secs, min_rect_secs,
min_poly_secs, min_arce_secs, min_bitblt_secs,
min_lmem_secs, min_gmem_secs, min_text_secs );
(**
** The following array is used to scan the checkbox
** buttons.
** NOTE: It's ordering is important!! It must
** correspond to the following set of constants.
** i.e., if pixel_test_id=1, then the first member
** of the button_id array MUST be ID__PIXEL_BUTTON.
**)
button_ids: ARRAY[1..11] OF Word =
( ID_PIXEL_BUTTON, ID_LINES_BUTTON, ID_RECTS_BUTTON,
ID_POLYS_BUTTON, ID_ARCE_BUTTON, ID_BITBLT_BUTTON,
ID_LMEM_BUTTON, ID_GMEM_BUTTON, ID_SFIO_BUTTON,
ID_RFIO_BUTTON, ID_TEXT_BUTTON );
(**
** Test ID numbers.
**)
pixel_test_id = 1;
line_test_id = 2;
rect_test_id = 3;
poly_test_id = 4;
arce_test_id = 5;
bitblt_test_id = 6;
lmem_test_id = 7;
gmem_test_id = 8;
sfio_test_id = 9;
rfio_test_id = 10;
texto_test_id = 11;
dtext_test_id = 12;
(**
** Test id max. Adjust this as you add more tests.
**)
max_test_id = 12;
max_num_tests = max_test_id;
(**
** Preferences. This is a section to be expanded in
** the future.
**)
pref_clipamt_id = 1; { Do clipping }
max_pref_id = 1;
(**
** Following constant array holds the number of "things per
** iteration" of each test.
**)
items_per_iter: ARRAY[1..max_test_id] OF LongInt =
( pixels_per_iter, lines_per_iter, rects_per_iter,
polys_per_iter, ellps_per_iter, bmap_points,
lmems_per_iter, gmems_per_iter,
1, 1,
text_per_iter, text_per_iter );
(**
** Following constants set default values for parameter
** of many of the benchmarks. These are initially loaded
** into variables.
** NOTE: Future version of benchmarks should make these
** values user-modifiable.
**)
{ Local memory benchmark }
max_local_memitems = 256;
max_local_memsize = 30000;
max_global_memitems = 512;
max_global_memsize = 1000000;
(**
** Text strings for displaying results.
**)
test_name: ARRAY [1..max_test_id] OF String[20] =
( 'Pixels: ', 'Lines: ', 'Rectangles: ', 'Polygons: ',
'Ellipses: ', 'BitBlts: ', 'Loc. Memory: ',
'Glob. Memory: ','Seq. File I/O: ', 'Rand. File I/O: ',
'TextOut: ', 'DrawText: ' );
(**
** Strings used in the TEXT benchmarks.
**)
bench_strs: ARRAY [0..5] OF String[50] =
( 'The Quick Brown Fox Jumped Over The Lazy Dog',
'Never Eat Anything Bigger Than Your HEAD',
'NEVER hold an electrical wire in your mouth',
'Where Do Pixels Go When Not Being Lit?',
'Do not lean forward as the bus pulls up!',
'Fried Rice should be eaten through the mouth');
DefLogName: String[13] = 'winbench.log';
DefCompName: String[13] = 'wincomp.dat';
{ Following used as a cheap source of dashed lines and blanks }
dashstr: PChar ='------------------------------------------------------------'#0;
blankstr: PChar = ' '#0;
{ Following defines # of bytes to set aside for each
entry in the data comparison file. }
compblocksize = 130;
(**********************
** TYPE DEFINITIONS **
**********************)
TYPE
ByteRec = RECORD { Chop a word into 2 bytes }
lo, hi: Byte;
END;
WordRec = RECORD { Chop a LongInt into 2 words }
lo, hi: Word;
END;
BigFileBuffType = ARRAY[0..39999] OF Char;
FileName = ARRAY[0..14] OF Char;
{ The following item, CompData, defines the record
layout of each entry in the comparison file. }
CompData = RECORD
description: ARRAY[0..70] of Char;
sysname: ARRAY[0..20] OF Char;
testresult: ARRAY[1..max_test_id] OF Real;
END;
PCompData = ^CompData;
(**********************
** GLOBAL VARIABLES **
**********************)
VAR
pens: ARRAY [0..7] OF HPen; { Handles for pens }
stopwatch: Longint; { Timer stopwatch holding var. }
(**
** The follow arrays keep track of elapsed time and number
** of iterations for each test.
**)
elapsedtsecarray: ARRAY[1..max_test_id] OF Longint;
iterarray: ARRAY[1..max_test_id] OF Longint;
(**
** Next items are special. The text benchmarks actually
** capture separate numbers. One set for TextOut and
** another for DrawText. In the results, the elapsed
** arrays hold the results for DrawText. These next
** variables hold the TextOut results.
**)
textoutelapsedtsecs: Longint;
textoutiters: Longint;
randl: ARRAY [0..1] OF LongInt; { Random number storage }
HByteWin: HWnd; { Handle to parent window }
pstruct: TPaintStruct; { Paint structure }
(**
** do_test_flags is an array that shows what tests
** are to be executed.
** tdo_test_flags holds a copy of the above array during
** editing of the configuration information, and allows
** the user to cancel his settings.
**)
do_test_flags: ARRAY[1..max_test_id] OF Bool;
tdo_test_flags: ARRAY[1..max_test_id] OF Bool;
pixel_secs: Word; { # of seconds to do pixels test }
line_secs: Word; { # of seconds to do lines test }
rect_secs: Word; { # of seconds to do rectangles test }
poly_secs: Word; { # of seconds to do polygons test }
arce_secs: Word; { # of seconds to do arc/ellipse test }
bitblt_secs: Word; { # of seconds to do bitblt test }
text_secs: Word; { # of seconds to do text test }
lmem_secs: Word; { # of seconds to do local memory test }
gmem_secs: Word; { # of seconds to do global memory test }
rfile_io_secs: Word; { # of seconds to do random file i/o test }
sfile_io_secs: Word; { # of seconds to do sequential file i/o test }
(**
** Following variables are used in the file I/O
** tests.
**)
sfilesize: LongInt; { Sequential file size }
sfilereclen: ARRAY [0..3] OF Integer; { Record lengths }
(**
** Preference settings.
**)
pref_settings: ARRAY[1..max_pref_id] OF Word;
{ Following vars. hold stuff for the standard alert }
{ dialog. If Count<>0, then x,y holds coordinates at }
{ which to display the text in AlertDlgText. }
(**
** Following vars are used to construct an alert dialog
** box...one that just has an "OK" in it.
** If ADTCount<>0, then ADTx and ADTy hold coordinates
** at which to display the text in AlertDlgText.
**)
ADTx, ADTy: Integer; { Coordinates to display text }
ADTCount: Integer; { Text count }
AlertDlgText: ARRAY[0..60] of Char;
logFileName :String[12]; {Log files are in current directory.}
autoLogAndExit: Boolean; {should we automatically write to log file and get out?}
logFile : Text;
bigFileBuff: ^BigFileBuffType;
totalRandomIoBytes: LongInt; {OK, I cheated, it shouldn't be a global.}
someTests : Boolean; { have we ever run any tests? }
CompFileName: ARRAY[0..14] of Char; { Comparison data file }
DataFile: Text; { File holding text comparison data }
iscompfilethere: Boolean; { Set to true if comp file is present }
{**
** DisplayBenchLine routines.
** Don't physically manipulate these yourself.
**}
benchLineHDC: HDC;
benchLineX: Integer;
benchLineY: Integer;
benchLineYInc: Integer;
benchLineHDCheight: Integer;
{**
** Following globals are used in handling the
** benchmark comparison dialog box.
**}
bcDispRect: TRect; { Display area }
bcBeginLine: Integer; { Beginning line to display }
bcTotNumLines: Integer; { Total # of lines to display }
bcNumLines: Integer; { # of lines in display area }
bcNumSystems: Integer; { # of systems in comparison file }
sysfontheight: Integer; { Height of system font }
ansiffontheight: Integer; { ANSI fixed font height }
{ Following array of handles is used to point to global
memory blocks where we'll store the data read in from
the comparison file. }
fbhand: ARRAY [1..5] of THandle;
{ The following pointer leads us to the acutal data stored
in the blocks referenced by each member of the fbhand[]
array. }
fbptr: PCompData; { Pointer to comparison data }
oldwinbkcolor: LongInt; { Save window background color }
(******************************
** ++ ROUTINES BEGIN ++ **
******************************)
{ ************** }
{ TIMER ROUTINES }
{ ************** }
{ ******************** }
{ START STOPWATCH }
{ Starts a stopwatch for benchmarking. }
PROCEDURE StartStopWatch;
BEGIN
stopwatch:=GetTickCount;
END;
{ ***************** }
{ STOP STOPWATCH }
{ This procedure turns off the stopwatch, calculates }
{ elapsed minutes, seconds, and 1/100 seconds and }
{ places the results in the global stopwatch }
{ variables. }
{ Note that this modifies the global elapsedticks }
PROCEDURE StopStopWatch;
VAR
elapsedticks: Longint;
BEGIN
stopwatch:=GetTickCount-stopwatch;
END;
(* ****************************************
** Accumulate into a timing array memeber
** Accumulate the elapsed time into a timing array
** entry selected by idx.
*)
PROCEDURE AccumTiming(idx: Word);
BEGIN
elapsedtsecarray[idx]:=elapsedtsecarray[idx]+stopwatch;
END; { AccumTiming }
{ *************************************** }
{ ** RANDOM NUMBER GENERATION ROUTINES ** }
{ *************************************** }
(* **************************
** Generate a random number
** Second order linear congruential R.N. generator.
** Constants suggested by J.G. Skellam.
** If longval==0, returns next number in sequence.
** If longval!=0, restarts generator.
** NOTE: The generator should be initially started
** with a call to Randnum(13);
**
*)
FUNCTION Randnum(longval: Longint) : Longint;
VAR
tlong: Longint; { Temp storage for long integer }
BEGIN
IF longval<>0 THEN
BEGIN
randl[0]:=longval;
randl[1]:=117;
END;
tlong:=randl[0]*254754 + randl[1]*529562;
tlong:=tlong MOD 999563;
randl[1]:=randl[0];
randl[0]:=tlong;
Randnum:=tlong;
END; { Randnum }
{ ********************************************* }
{ Get a random number with a specified ceiling. }
FUNCTION GetRandWithCeiling(ceiling: LongInt): LongInt;
BEGIN
IF ceiling=0 THEN
BEGIN
GetRandWithCeiling:=0;
Exit;
END;
GetRandWithCeiling:=Randnum(0) MOD (ceiling+1);
END; { GetRandWithCeiling }
{********************************************
** Delay a passed number of seconds.
**}
PROCEDURE DelaySeconds( cnt: Integer );
VAR
StartTick: LongInt;
ThisTick: LongInt;
Delay: LongInt;
BEGIN
StartTick := GetTickCount;
ThisTick := GetTickCount;
Delay := cnt * 1000; { ticks are in milliseconds}
while( Delay > (ThisTick - StartTick) )
do begin
ThisTick := GetTickCount;
END;
END;
(**********************************************
** Get the system and ANSI fixed font's height.
** A bunch of routines need this for display.
**)
PROCEDURE GetFontHeight;
VAR
BWHDC: Hdc; { Device context }
fmetrics: tTextMetric; { Grab text metrics }
BEGIN
BWHDC:=GetDC(HByteWin);
SelectObject(BWHDC,GetStockObject(ANSI_Fixed_Font));
GetTextMetrics(BWHDC,fmetrics);
ansiffontheight:=fmetrics.tmHeight;
SelectObject(BWHDC,GetStockObject(System_Font));
GetTextMetrics(BWHDC,fmetrics);
sysfontheight:=fmetrics.tmHeight;
ReleaseDC(HByteWin,BWHDC);
END; { GetSysFontHeight }
(*
** Erase the client area
*)
PROCEDURE EraseClient;
VAR
xmin, xmax: Integer; { X clipping bounds }
ymin, ymax: Integer; { Y clipping bounds }
HisRect: TRect; { Client rectangle }
HDevCont: HDC; { Device context }
BEGIN
{ Get a device context for the window }
HDevCont:=GetDC(HByteWin);
{ Black brush, null pen }
SelectObject(HdevCont,GetStockObject(Black_Brush));
SelectObject(HdevCont,GetStockObject(Black_Pen));
{ Get the rectangle coordinates }
GetClientRect(HByteWin,HisRect);
xmin:=HisRect.left;
ymin:=HisRect.top;
xmax:=HisRect.right;
ymax:=HisRect.bottom;
{ Paint the rectangle }
Rectangle(HdevCont,xmin,ymin,xmax,ymax);
{ Release the context }
ReleaseDC(HBytewin, HDevCont);
END;
{********************************************
** Initialize the display variables.
**}
PROCEDURE InitBenchDisplay;
var
fmetrics: TTextMetric; { For grabbing font metrics }
begin
BenchLineHDC := GetDC( HByteWin );
BenchLineX := 10;
{ Set us up with the system font }
SelectObject( BenchLineHDC, GetStockObject(System_Font) );
{ Determine starting coordinates }
GetTextMetrics( BenchLineHDC, fmetrics );
{ BenchLineY := fmetrics.tmHeight;
BenchLineYInc := BenchLineY; }
BenchLineY := sysfontheight;
BenchLineYInc:= sysfontheight;
{ Clear the client window }
EraseClient;
{ Set foreground and background colors }
SetTextColor( BenchLineHDC, RGB(255,255,255) );
SetBkColor( BenchLineHDC, RGB(0,0,0) );
SetBkMode( BenchLineHDC, Opaque );
end;
PROCEDURE CloseBenchDisplay;
begin
{ Release the display context }
ReleaseDC(HByteWin, BenchLineHDC );
end;
(********************************************
** Display a single line of benchmark results
*********************************************
** Pass this function the string to be displayed and the
** initial coordinates. It returns the height of the
** string, which can be used to position the next string
** in sequence.
** Note, I'm using globals all over the place which is rather messy.
** Still, its a lot cleaner than displaying each time.
** Definitely needs a rethink.
*)
FUNCTION DisplayBenchLine( hisstring: PChar; hisstringlen: Integer): Integer;
VAR
tlong: Longint; { Temp long integer }
BEGIN
if( BenchLineHDC <> 0 ) { ensure we've setup an HDC }
then begin
TextOut(BenchLineHDC, BenchLineX, BenchLineY, hisstring, hisstringlen);
tlong := GetTextExtent(BenchLineHDC, hisstring, hisstringlen );
DisplayBenchLine := WordRec(tlong).hi;
BenchLineY := BenchLineY + WordRec(tlong).hi;
end;
END; { DisplayBenchLine }
{ *************************************** }
{ WINDOWS INITIALIZATION ROUTINES }
{ *************************************** }
PROCEDURE setParm( parmString: String );
BEGIN
if( '-L' = parmString )
then begin
autoLogAndExit := TRUE;
end;
if( not (Pos( '-', parmString ) = 1) )
then begin
{ not a flag -- must be the name of the log file.
{ note: we're not checking for validity here. but we do ensure proper length.}
logFileName := Copy( parmString, 1, 12 );
end;
END; {setParm }
{ *********************************** }
{ Initialize any parameters from the command line. }
PROCEDURE InitCommandLineParameters;
VAR
i: Integer; { Loop index }
lastParm : Integer; { number of parameters on command line }
parmString : String; { a particular command line parameters }
BEGIN
lastParm := Paramcount;
if( lastParm > 0 )
THEN BEGIN
for i:= 1 to lastParm
do BEGIN
parmString := ParamStr( i );
setParm( parmString );
END;
END;
END;
{ *********************************** }
{ Initialize all the global variables }
PROCEDURE InitGlobals;
VAR
i: Integer; { Loop index }
fpath: ARRAY[0..fsPathName] of CHAR; { File path }
BEGIN
{ Set times to their defaults }
pixel_secs:=min_pixel_secs;
line_secs:=min_line_secs;
rect_secs:=min_rect_secs;
poly_secs:=min_poly_secs;
arce_secs:=min_arce_secs;
bitblt_secs:=min_bitblt_secs;
text_secs:=min_text_secs;
lmem_secs := min_lmem_secs;
gmem_secs := min_gmem_secs;
rfile_io_secs := min_rfile_io_secs; {current interface does not use this, code does}
sfile_io_secs := min_sfile_io_secs; {current interface/code does not use this }
{ Set other defaults }
sfilesize:=5000000; { Seq. file is 5 million characters }
sfilereclen[0]:=256; { Seq. file record lengths }
sfilereclen[1]:=512;
sfilereclen[2]:=1024;
sfilereclen[3]:=4096;
{ Check all the checkboxes }
FOR i:=1 TO max_test_id DO
do_test_flags[i]:=TRUE;
{ Initialize the random number generator }
Randnum(13);
{ Initialize the log file. }
LogFileName := DefLogName;
autoLogAndExit := FALSE;
InitCommandLineParameters;
someTests := FALSE; { no tests have yet been run }
{ Search for the comparison data file. Set appropriate
flag depending on whether or the file is present or not. }
StrPCopy(CompFileName,DefCompName);
FileSearch(fpath,CompFileName,'');
IF fpath[0]=#0 THEN
iscompfilethere:=FALSE
ELSE
BEGIN
iscompfilethere:=TRUE;
Assign(DataFile,CompFileName);
END;
{ Get the height of the system font }
GetFontHeight;
{ Initialize the benchdisplayline variables. }
benchLineX := 0;
benchLineY := 0;
benchLineYInc:= 0;
benchLineHDC := 0;
END; { InitGlobals }
{ ********************************** }
{ ** DIALOG BOX HANDLING ROUTINES ** }
{ ********************************** }
(* ****************************************
** Given a button id, return the test id.
*)
FUNCTION ButtonToTestID(buttonid: Word) : Word;
VAR
i: Word; { Index variable }
BEGIN
ButtonToTestID:=0;
(* Step through the button_ids[] array looking
** for a match. Exit with index value when
** you find one.
*)
FOR i:=1 TO max_test_id DO
IF button_ids[i]=buttonid THEN
BEGIN
ButtonToTestID:=i;
Exit;
END;
END; { ButtonToTestID }
(* *******************************************
** Save benchmark configuration settings in
** temporary storage. Call this routine
** when the configuration dialog box is first
** opened. This lets the system restore the
** initial setting if a CANCEL is hit.
*)
PROCEDURE SaveConfigToTemp;
VAR
i: Integer; { Index variable }
BEGIN
FOR i:=1 TO max_test_id DO
tdo_test_flags[i]:=do_test_flags[i];
END; { SaveConfigToTemp }
(* ********************************************
** Restore benchmark configuration settings
** from temporary storage. Call this routine
** if a CANCEL button is hit.
*)
PROCEDURE RestoreConfigFromTemp;
VAR
i: Integer; { Integer variable }
BEGIN
FOR i:=1 TO max_test_id DO
do_test_flags[i]:=tdo_test_flags[i];
END; { RestoreConfigFromTemp }
{ ************************************************ }
{ Verify that defaults selected are within bounds. }
{ This function examines the selected defaults and }
{ returns 0 if they're all ok. Otherwise, it }
{ returns the ID+1 of the first editbox that holds }
{ disallowed values. }
FUNCTION CheckInBounds(HDialog : HWnd): Word;
VAR
i: Word; { Used as index }
secs: Integer; { Seconds }
transflag: Bool; { Translation flag }
BEGIN
FOR i:= 0 TO 7 DO
BEGIN
secs:=GetDlgItemInt(HDialog,edit_box_ids[i],
@transflag, TRUE);
IF (transflag=FALSE) OR (secs<edit_box_mins[i])
THEN
BEGIN
CheckInBounds:=i+1;
Exit;
END;
END; { FOR loop }
CheckInBounds:=0;
END; { CheckInBounds }
{ ******************************************************* }
{ Load the settings of the benchmark configuration dialog }
{ box into the proper global variables. By the time }
{ this routine is called, we've verified that all the }
{ entered numbers are legit. }
PROCEDURE GetBenchConfigSettings( HDialog : HWnd);
VAR
i: Word; { Used as index }
secs: Integer; { Seconds }
transflag: Bool; { Translation flag }
BEGIN
{ First get all the edit box contents }
pixel_secs:=GetDlgItemInt(HDialog,ID_PIXEL_SECS,
@transflag, TRUE);
line_secs:=GetDlgItemInt(HDialog,ID_LINE_SECS,
@transflag, TRUE);
rect_secs:=GetDlgItemInt(HDialog,ID_RECT_SECS,
@transflag, TRUE);
poly_secs:=GetDlgItemInt(HDialog,ID_POLY_SECS,
@transflag, TRUE);
arce_secs:=GetDlgItemInt(HDialog,ID_ARCE_SECS,
@transflag, TRUE);
bitblt_secs:=GetDlgItemInt(HDialog,ID_BITBLT_SECS,
@transflag, TRUE);
text_secs:=GetDlgItemInt(HDialog,ID_TEXT_SECS,
@transflag, TRUE);
END; { GetBenchConfigSettings }
(* *********************************
** Handle a standard alert dialog.
** We'll define a "standard alert dialog" to be a dialog
** box that informs the user of some outstanding condition.
** The only thing the user can do is hit the OK button.
*)
FUNCTION StandardAlertDialog(Dialog: HWnd; Message, WParam: Word;
LParam: LongInt): Bool; export;
VAR
DlgDC: HDC; { Context for dialog }
HMDevCont: HDC; { Memory context }
bithand: HBitmap; { Handle for bitmap }
BEGIN
CASE Message OF
wm_InitDialog:
BEGIN
IF ADTCount>0 THEN
SetDlgItemText(Dialog, IDL_Logfield, AlertDlgText);
{ Set the focus }
SetFocus(GetDlgItem(Dialog,IDB_OK));
StandardAlertDialog:=FALSE;
EXIT;
END;
wm_Paint:
BEGIN
IF ADTCount<0 THEN
{ A negative ADTCount is a sneaky way of telling us
to display the BYTE Logo. }
BEGIN
DlgDC:=GetDC(Dialog);
bithand:=LoadBitMap(HInstance,'BYTELOGO');
HMDevCont:=CreateCompatibleDC(DlgDC);
SelectObject(HMDevCont,bithand);
BitBlt(DlgDC,125,10,200,68,HMDevCont,0,0,SrcCopy);
DeleteDC(HMDevCont);
ReleaseDC(Dialog,DlgDC);
DeleteObject(bithand);
END;
StandardAlertDialog:=FALSE;
END;
wm_Command:
CASE WParam OF
IDB_OK:
BEGIN
EndDialog(Dialog,0);
StandardAlertDialog:=TRUE;
ADTCount:=0; { Don't need string }
EXIT;
END;
END; { CASE WParam }
END; { CASE Message }
StandardAlertDialog:=FALSE;
END; { StandardAlertDialog }
FUNCTION getLogNameDialogAction( Dialog: HWnd; Message, WParam: Word;
LParam: LongInt ): Bool; export;
VAR
DlgDC: HDC; { Context for dialog }
theName: ARRAY [0..14] of CHAR;
strName: String[13];
BEGIN
CASE Message OF
wm_InitDialog:
BEGIN
StrPCopy( theName, logfileName );
SetDlgItemText(Dialog, IDL_Logfield, theName );
{ Set the focus }
SetFocus(GetDlgItem(Dialog,IDL_logfield));
getLogNameDialogAction:=FALSE;
EXIT;
END;
wm_Command:
CASE WParam OF
IDL_OK: {grab the new logfile -- eventually do error checking }
BEGIN
EndDialog(Dialog,0);
getLogNameDialogAction:=TRUE;
GetDlgItemText( Dialog, IDL_LogField, theName, 13);
strName := StrPas( theName );
{ do error checking here -- if ok, then ...}
logFileName := strName;
EXIT;
END;
IDL_CANCEL: {don't change the logfile name}
BEGIN
EndDialog( Dialog, 0 );
getLogNameDialogAction := TRUE;
EXIT;
END;
END; { CASE WParam }
END; { CASE Message }
getLogNameDialogAction:=FALSE;
END;
{ ************************************* }
{ Handle the set-to-defaults dialog box }
{ This dialog box simply accepts a yes/no response. }
{ Yes sets benchmark configurations to their }
{ defaults...no leaves them unchanged. }
FUNCTION SetToDefaultsDialog(Dialog: HWnd; Message, WParam: Word;
LParam: LongInt): Bool; export;
BEGIN
CASE Message OF
wm_InitDialog:
BEGIN
{ Set the focus }
SetFocus(GetDlgItem(Dialog,IDB_OK));
SetToDefaultsDialog:=FALSE;
EXIT;
END;
wm_Command:
BEGIN
CASE WParam OF
IDB_OK:
BEGIN
{ Set all items to default }
EndDialog(Dialog,0);
SetToDefaultsDialog:=TRUE;
EXIT;
END;
IDB_CANCEL:
BEGIN
EndDialog(Dialog,0);
SetToDefaultsDialog:=TRUE;
EXIT;
END;
END; { CASE WParam }
END; { BEGIN }
END; { CASE Message }
SetToDefaultsDialog:=FALSE;
END; { SetToDefaultsDialog }
(* **********************
** Flip a dialog button
** This routine flips the state of a dialog button.
*)
FUNCTION FlipButton(Dialog: HWnd; button_id: Integer;
curr_state : Bool) : Bool;
BEGIN
IF curr_state=TRUE THEN
BEGIN
CheckDlgButton(Dialog,button_id,0);
FlipButton:=FALSE;
END
ELSE
BEGIN
CheckDlgButton(Dialog,button_id,1);
FlipButton:=TRUE;
END;
END; { FlipButton }
{ ********************************************* }
{ Handle the benchmark configuration dialog box }
{ This is the big, nasty dialog box that gets }
{ benchmark configuration settings. We grab }
{ stuff into a temporary area when we get an }
{ init dialog message. If the use hits an ok, }
{ we copy the temporary area into the real }
{ variables...if the user hits cancel, we dump }
{ the temporary stuff and keep the real }
{ variables unchanged. }
FUNCTION BenchConfigDialog(Dialog: HWnd; Message, WParam: Word;
LParam: LongInt): Bool; export;
VAR
test_id: Word; { Test Identification number }
i: Integer; { Index value }
BEGIN
BenchConfigDialog:=True;
CASE Message OF
wm_InitDialog: { ** INITIALIZE DIALOG BOX ** }
BEGIN
{ Copy current into temporary variables }
SaveConfigToTemp;
{ Set buttons based on current values }
FOR i:=1 TO max_test_id DO
IF do_test_flags[i] THEN
CheckDlgButton(Dialog,button_ids[i],1)
ELSE
CheckDlgButton(Dialog,button_ids[i],0);
{ Set edit boxes based on current values }
SetDlgItemInt(Dialog,ID_PIXEL_SECS,pixel_secs, TRUE);
SetDlgItemInt(Dialog,ID_LINE_SECS,line_secs, TRUE);
SetDlgItemInt(Dialog,ID_RECT_SECS,rect_secs, TRUE);
SetDlgItemInt(Dialog,ID_POLY_SECS,poly_secs, TRUE);
SetDlgItemInt(Dialog,ID_ARCE_SECS,arce_secs, TRUE);
SetDlgItemInt(Dialog,ID_BITBLT_SECS,bitblt_secs, TRUE);
SetDlgItemInt(Dialog,ID_TEXT_SECS,text_secs,TRUE);
{ Set the focus }
SetFocus(GetDlgItem(Dialog,IDB_OK));
BenchConfigDialog:=FALSE;
EXIT;
END;
wm_Command: { ** HANDLE COMMAND ACTION ** }
CASE WParam OF
IDB_OK: { ** OK Button ** }
BEGIN
(* Make sure all the settings make sense and
** are within bounds. If not, throw up an
** alert dialog and keep things as they
** are. If so, read the benchmark configurations
** to make them current and get rid of the
** dialog box.
*)
IF CheckInBounds(Dialog)<> 0 THEN
BEGIN
(* Throw up alert *)
MessageBeep(0);
END
ELSE
BEGIN
(* All is well *)
GetBenchConfigSettings(Dialog);
END;
EndDialog(Dialog,NULL);
BenchConfigDialog:=TRUE;
EXIT;
END;
IDB_CANCEL: { ** Cancel button ** }
BEGIN
(* Set everything back to the way it
** was before the dialog box was
** opened. Then shut down.
*)
RestoreConfigFromTemp;
EndDialog(Dialog,NULL);
BenchConfigDialog:=TRUE;
EXIT;
END;
ID_PIXEL_BUTTON, { ** Pixel test button ** }
ID_LINES_BUTTON, { ** Lines test button ** }
ID_RECTS_BUTTON, { ** Rectangles test button ** }
ID_POLYS_BUTTON, { ** Polygons test button ** }
ID_ARCE_BUTTON, { ** Arc/ellipse test button ** }
ID_BITBLT_BUTTON, { ** BitBlt test button ** }
ID_LMEM_BUTTON, { ** Local memory test button ** }
ID_GMEM_BUTTON, { ** Global memory test button ** }
ID_SFIO_BUTTON, { ** Seq. file i/o test button ** }
ID_RFIO_BUTTON, { ** Rand. file i/o test button ** }
ID_TEXT_BUTTON: { ** Text test button ** }
BEGIN
test_id:=ButtonToTestID(WParam);
do_test_flags[test_id]:=FlipButton(Dialog,WParam,
do_test_flags[test_id]);
BenchConfigDialog:=TRUE;
EXIT;
END;
ELSE
BEGIN
BenchConfigDialog:=FALSE;
EXIT;
END;
END; { CASE WParam }
ELSE
BEGIN
BenchConfigDialog:=FALSE;
EXIT;
END;
END; { CASE Message }
END; { BenchConfigDialog }
(**********************************
** DEVICE CONFIGURATION ROUTINES **
**********************************)
(****************************************
** Show the current system configuration.
** This routine displays stuff like
** processor/coprocessor type, screen size, etc.
*)
PROCEDURE ShowDevConfig;
BEGIN
{ Call assembly routine to determine processor and }
{ coprocessor type/presence. }
{ Call GetDeviceCaps for screen info. }
{ Clear the display area }
{ Display the information and return }
END; { ShowDevConfig }
{ ************************************ }
{ ** BENCHMARK ROUTINES THEMSELVES! ** }
{ ************************************ }
FUNCTION LMin(a,b: Integer): Longint;
BEGIN
IF a<b THEN LMin:=a ELSE LMin:=b;
END;
(*************************
** Local Memory benchmark
** This procedure executes the local memory test.
*)
PROCEDURE LMemTest;
VAR
i: Integer; { Array index }
numreqs: Word; { # of requests }
locsize: Word; { Size of local memory in bytes }
memhandles: ARRAY[0..1000] OF THandle; { Memory handles }
reqsizes: ARRAY[0..1000] OF LongInt; { Request sizes }
totrequest: LongInt; { Total request }
memflags1: Word; { Flags for requests }
memflags2: Word; { Flags for requests }
tmemptr: Pointer; { Temp. for holding pointer }
dlgproc: TFarProc; { Procedure instance }
reqsize: LongInt; { Total request size }
tstring: Array[0..8] of Char; { Temp string for conversion }
temphand: THandle; { Temp handle }
outstr: Array [0..80] of Char; { message to display }
outstrlen: Integer; { need to know how long it is }
BEGIN
InitBenchDisplay;
strPCopy( @outstr, 'Running local memory test.');
outstrlen := StrLen( @outstr );
DisplayBenchLine( @outstr, outstrlen );
{ Clear the timer array }
elapsedtsecarray[lmem_test_id]:=0;
iterarray[lmem_test_id]:=0;
{ ** LOCAL MEMORY TEST ** }
{ Determine amount of local memory with call... }
{ ... to LocalCompact(). If this is less than }
{ 32K, then we've got a problem. }
locsize:=LocalCompact(max_local_memsize);
IF locsize<31000 THEN
BEGIN
(* Handle problem of < 32K of local memory. This should
** throw up a dialog box that says "Not enough memory for
** local test." With just an OK. After the user clicks
** the OK, the dialog box goes away and this function
** exits.
*)
ADTx:=28; { Display current memory in dialog }
ADTy:=30;
Str(locsize DIV 1024,tstring);
StrCopy(@AlertDlgText,'(');
StrCat(@AlertDlgText,@tstring);
StrCat(@AlertDlgText,'K Free)');
ADTCount:=StrLen(@AlertDlgText);
dlgproc:=MakeProcInstance(@StandardAlertDialog,HInstance);
DialogBox(HInstance,'NOMEMDLG',HByteWin,dlgproc);
FreeProcInstance(dlgproc);
Exit;
END;
{ Generate a random array of memory requests. }
{ Each request is no less than 32 bytes and }
{ no greater than 512 bytes. Furthermore, }
{ the sum of all requests will not exceed }
{ a specified amount. }
numreqs:=0;
totrequest:=0;
REPEAT
BEGIN
reqsize:=ABS(GetRandWithCeiling(480))+32;
reqsizes[numreqs]:=reqsize;
Inc(numreqs);
totrequest:=totrequest+reqsize;
END
UNTIL (numreqs=max_local_memitems) OR (totrequest>max_local_memsize);
{ Set up the flags word for upcoming requests }
memflags1:=lmem_Moveable OR lmem_ZeroInit;
memflags2:=lmem_Moveable;
locsize:=0;
{ Enter timing loop }
WHILE (elapsedtsecarray[lmem_test_id] DIV 1000)<lmem_secs DO
BEGIN
{ Start timing }
StartStopwatch;
{ Step through the array, calling LocalAlloc(). }
{ Blocks are moveable and memory is not discarded }
{ or compacted. Also, memory is initialized. }
FOR i:=0 TO numreqs-1 DO
memhandles[i]:=LocalAlloc(memflags1, WordRec(reqsizes[i]).lo);
{ Step through the array and lock every other block. }
FOR i:=0 TO ((numreqs-1) DIV 2) DO
tmemptr:=LocalLock(memhandles[i+i]);
{ Call LocalCompact() with nonzero argument }
LocalCompact(8000);
{ Step through array, unlocking and freeing blocks }
{ locked in previous step. Add amount freed to }
{ localsize variable. }
{ NOTE: LATER VERSIONS SHOULD PUT CHECK ON THE }
{ LOCALFREE() CALL TO VERIFY THAT IT EXECUTED }
{ PROPERLY. }
FOR i:=0 TO ((numreqs-1) DIV 2) DO
BEGIN
LocalUnlock(memhandles[i+i]);
locsize:=locsize+reqsizes[i+i];
LocalFree(memhandles[i+i]);
END;
{ Go through the array of remaining blocks, issuing }
{ a LocalReAlloc on those blocks, expanding each }
{ so that it consumes remaining memory. Then free }
{ that block and go on to the next. }
{ NOTE: CHECK THIS LOOP!!! ARE THE PARAMS OK??? }
FOR i:=0 TO ((numreqs-2) DIV 2) DO
BEGIN
temphand:=
LocalRealloc(memhandles[i+i+1],reqsizes[i+i+1]+locsize,memflags2);
IF temphand<>0 THEN memhandles[i+i+1]:=temphand;
LocalFree(memhandles[i+i+1]);
locsize:=locsize+reqsizes[i+i+1];
END;
{ Stop timing and record results }
StopStopWatch;
{ Increment iterations and accumulate seconds }
Inc(iterarray[lmem_test_id]);
AccumTiming(lmem_test_id);
END; { While }
END; { LmemTest }
(*********************
** Global memory test
** This procedure executes the global memory test.
*)
PROCEDURE GMemTest;
VAR
i: Integer; { Array index }
numreqs: Word; { # of requests }
memhandles: ARRAY[0..1000] OF THandle; { Memory handles }
reqsizes: ARRAY[0..1000] OF LongInt; { Request sizes }
totrequest: LongInt; { Total request }
memflags1: Word; { Flags for requests }
memflags2: Word; { Flags for requests }
tmemptr: Pointer; { Temp. for holding pointer }
globsize: LongInt; { Size of largest global block }
dlgproc: TFarProc; { Procedure instance }
reqsize: LongInt; { Max request size }
tstring: Array[0..8] of Char; { Temp string for conversion }
temphand: THandle; { Temporary handle }
outstr: Array [0..80] of Char; { message to display }
outstrlen: Integer; { need to know how long it is }
BEGIN
InitBenchDisplay;
strPCopy( @outstr, 'Running global memory test.');
outstrlen := StrLen( @outstr );
DisplayBenchLine( @outstr, outstrlen );
{ Clear timing }
elapsedtsecarray[gmem_test_id]:=0;
iterarray[gmem_test_id]:=0;
{ Determine amount of Global memory with call... }
{ ... to GlobalCompact(). If this is less than }
{ 1024K, then we've got a problem. }
globsize:=GlobalCompact(1050000);
globsize:=GetFreeSpace(0);
IF globsize<1048576 THEN
BEGIN
(* Handle problem of < 1M of global memory. This should
** throw up a dialog box that says "Not enough memory for
** global test." With just an OK. After the user clicks
** the OK, the dialog box goes away and this function
** exits.
*)
ADTx:=28; { Display current memory in dialog }
ADTy:=30;
Str(globsize DIV 1024,tstring);
StrCopy(@AlertDlgText,'(');
StrCat(@AlertDlgText,@tstring);
StrCat(@AlertDlgText,'K Free)');
ADTCount:=StrLen(@AlertDlgText);
dlgproc:=MakeProcInstance(@StandardAlertDialog,HInstance);
DialogBox(HInstance,'NOMEMDLG',HByteWin,dlgproc);
FreeProcInstance(dlgproc);
Exit;
END;
{ Generate a random array of memory requests. }
{ Each request is no less than 512 bytes and }
{ no greater than 4K bytes. Furthermore, }
{ the sum of all requests will not exceed }
{ a specified amount. }
numreqs:=0;
totrequest:=0;
REPEAT
BEGIN
reqsize:=ABS(GetRandWithCeiling(3584))+512;
reqsizes[numreqs]:=reqsize;
Inc(numreqs);
totrequest:=totrequest+reqsize;
END
UNTIL (numreqs=max_global_memitems) OR (totrequest>max_global_memsize);
{ Set up the flags words for upcoming requests }
memflags1:=gmem_Moveable OR gmem_ZeroInit;
memflags2:=gmem_Moveable;
globsize:=0;
{ Enter timing loop }
WHILE (elapsedtsecarray[gmem_test_id] DIV 1000)<gmem_secs DO
BEGIN
{ Start timing }
StartStopwatch;
{ Step through the array, calling GlobalAlloc(). }
{ Blocks are moveable and memory is not discarded }
{ or compacted. Also, memory is initialized. }
FOR i:=0 TO numreqs-1 DO
BEGIN
memhandles[i]:=GlobalAlloc(memflags1, reqsizes[i]);
IF memhandles[i]=0 THEN MessageBeep(0);
END;
{ Step through the array and lock every other block. }
FOR i:=0 TO ((numreqs-1) DIV 2) DO
tmemptr:=GlobalLock(memhandles[i+i]);
{ Call GlobalCompact() with nonzero argument }
GlobalCompact(1000);
{ Step through array, unlocking and freeing blocks }
{ locked in previous step. Add amount freed to }
{ globalsize variable. }
{ NOTE: LATER VERSIONS SHOULD PUT CHECK ON THE }
{ GLOBALFREE() CALL TO VERIFY THAT IT EXECUTED }
{ PROPERLY. }
FOR i:=0 TO ((numreqs-1) DIV 2) DO
BEGIN
GlobalUnlock(memhandles[i+i]);
globsize:=globsize+reqsizes[i+i];
memhandles[i+i]:=GlobalFree(memhandles[i+i]);
IF memhandles[i+i]<>0 THEN MessageBeep(0);
END;
{ Go through the array of remaining blocks, issuing }
{ a GlobalReAlloc on those blocks, expanding each }
{ so that it consumes remaining memory. Then free }
{ that block and go on to the next. }
FOR i:=0 TO ((numreqs-2) DIV 2) DO
BEGIN
temphand:=
GlobalRealloc(memhandles[i+i+1],reqsizes[i+i+1]+globsize,memflags2);
IF temphand<>0 THEN memhandles[i+i+1]:=temphand;
memhandles[i+i+1]:=GlobalFree(memhandles[i+i+1]);
IF memhandles[i+i+1]<>0 THEN MessageBeep(0);
globsize:=globsize+reqsizes[i+i+1];
END;
{ Stop timing and record results }
StopStopWatch;
{ Increment iterations and accumulate seconds }
Inc(iterarray[gmem_test_id]);
AccumTiming(gmem_test_id);
END; { While }
END; { GMemTest }
{ *************************** }
{ GRAPHICS BENCHMARK ROUTINES }
{ *************************** }
{ **************** }
{ Pixels benchmark }
PROCEDURE PixelTest;
VAR
xmin, xmax: Integer; { X clipping bounds }
ymin, ymax: Integer; { Y clipping bounds }
xloc: ARRAY [0..pixels_per_iter] OF Integer; { X coordinates array }
yloc: ARRAY [0..pixels_per_iter] OF Integer; { Y coordinates array }
colors: ARRAY [0..pixels_per_iter] OF LongInt; { Colors array }
i: Word; { Loop index }
tlongint: LongInt; { Temp long integer }
redval: Byte; { Holds RED value }
greenval: Byte; { Holds GREEN value }
blueval: Byte; { Holds BLUE value }
HDevCont: HDC; { Device context }
HisRect: TRect; { Client rectangle }
menuhand: HMenu; { Handle for menu }
omenuhand: HMenu; { Old menu handle }
BEGIN
{ Set up the proper menu }
menuhand:=LoadMenu(HInstance,'PIXMENU');
omenuhand:=GetMenu(HByteWin);
SetMenu(HByteWin,menuhand);
{ Determine the clipping bounds for this test. }
GetClientRect(HByteWin,HisRect);
xmin:=HisRect.left;
ymin:=HisRect.top;
xmax:=HisRect.right;
ymax:=HisRect.bottom;
{ Clear the timing arrays }
elapsedtsecarray[pixel_test_id]:=0;
iterarray[pixel_test_id]:=0;
{ Build an array of color references }
FOR i:=0 TO pixels_per_iter DO
BEGIN
tlongint:=Randnum(0);
redval:=ByteRec(WordRec(tlongint).lo).lo;
tlongint:=Randnum(0);
greenval:=ByteRec(WordRec(tlongint).lo).lo;
tlongint:=Randnum(0);
blueval:=ByteRec(WordRec(tlongint).lo).lo;
colors[i]:=PaletteRGB(redval,greenval,blueval);
END;
{ Get a device context }
HDevCont:=GetDC(HByteWin);
{ ** SetPixel ** }
{ Enter timing loop }
WHILE (elapsedtsecarray[pixel_test_id] DIV 1000)<pixel_secs DO
BEGIN
{ Clear client window }
EraseClient;
{ Build a random array of x and y locations }
FOR i:=0 TO pixels_per_iter DO
BEGIN
tlongint:=xmax-xmin;
tlongint:=ABS(GetRandWithCeiling(tlongint))+xmin;
xloc[i]:=WordRec(tlongint).lo;
tlongint:=ymax-ymin;
tlongint:=ABS(GetRandWithCeiling(tlongint))+ymin;
yloc[i]:=WordRec(tlongint).lo;
END;
{ Start timing }
StartStopWatch;
{ Step through array, writing pixels to screen }
FOR i:=0 TO pixels_per_iter DO
SetPixel(HDevCont,xloc[i],yloc[i],colors[i]);
{ Stop timing }
StopStopWatch;
{ Increment iterations and accumulate seconds }
Inc(iterarray[pixel_test_id]);
AccumTiming(pixel_test_id);
END; { While }
(*
** NOTE: The GetPixel test has been eliminated in this
** version of the benchmarks. It seems to be a pointless
** test, since few applications use this feature.
** We may resurrect it in later versions. --RG
**
{ ** GetPixel ** }
{ Enter timing loop }
WHILE elapsedminarray[1]*60+elapsedtsecarray[1]<pixel_secs DO
BEGIN
{ Start timing }
StartStopWatch;
{ Step through the array, reading pixels }
FOR i:=0 TO pixels_per_iter DO
tlongint:=GetPixel(HDevCont,xloc[i],yloc[i]);
{ Stop timing }
StopStopWatch;
{ Increment iterations and accumulate seconds }
Inc(iterarray[1]);
AccumTiming(1);
END; { While }
*)
{ Show that we're done painting }
ReleaseDC(HByteWin,HDevCont);
{ Put menu back the way it was }
SetMenu(HByteWin,omenuhand);
DestroyMenu(menuhand);
END; { PixelTest }
{ **************** }
{ Make some pens }
{ This procedure is called prior to doing the graphics }
{ tests. It creates a set of 8 pens and loads them }
{ into the global array pens[]. The graphics tests }
{ that use pens use the array pens[]. }
PROCEDURE MakePens;
VAR
redval: Integer; { Red value }
greenval: Integer; { Green value }
blueval: Integer; { Blue value }
i: Integer; { Index }
j: Integer; { Another index }
BEGIN
{ Create a collection of pens...8 in all }
redval:=0;
greenval:=0;
blueval:=0;
FOR i:=0 TO 7 DO
BEGIN
IF (i AND 1)=1 THEN redval:=255 ELSE redval:=0;
IF (i AND 2 )=2 THEN greenval:=255 ELSE greenval:=0;
IF (i AND 4 )=4 THEN blueval:=255 ELSE blueval:=0;
pens[i]:=CreatePen(ps_Solid,1,
RGB(redval,greenval,blueval));
END; { FOR }
END; { MakePens }
{ ***************** }
{ Delete those pens }
{ Delete the pens make by MakePens () }
PROCEDURE DeletePens;
VAR
i: Integer; { Index }
BEGIN
FOR i:=0 TO 7 DO
DeleteObject(pens[i]);
END; { DeletePens }
{ *************** }
{ Lines Benchmark }
PROCEDURE LineTest;
VAR
xyloc: ARRAY [0..3,0..lines_per_iter] OF Integer; { Coordinates array }
i: Word; { Index variable }
j: Word; { Another index variable }
tlongint: LongInt; { Temporary long integer }
HDevCont: HDC; { Device context }
mypen: HPen; { Current pen }
xmin, xmax: Integer; { X clipping bounds }
ymin, ymax: Integer; { Y clipping bounds }
HisRect: TRect; { Client rectangle }
menuhand: HMenu; { Handle for menu }
omenuhand: HMenu; { Old menu handle }
BEGIN
{ Set up the proper menu }
menuhand:=LoadMenu(HInstance,'LINEMENU');
omenuhand:=GetMenu(HByteWin);
SetMenu(HByteWin,menuhand);
{ Make some pens }
MakePens;
{ Clear the timing arrays }
elapsedtsecarray[line_test_id]:=0;
iterarray[line_test_id]:=0;
{ For now...no clipping }
pref_settings[pref_clipamt_id]:=0;
{ Determine the clipping bounds for this test. }
GetClientRect(HByteWin,HisRect);
xmin:=HisRect.left;
ymin:=HisRect.top;
xmax:=HisRect.right;
ymax:=HisRect.bottom;
{ Begin the loop. Execute inner loops until the outer-loop }
{ number of seconds is satisfied. }
WHILE (elapsedtsecarray[line_test_id] DIV 1000)<line_secs DO
BEGIN
{ Build array of endpoints }
FOR i:=0 TO lines_per_iter DO
FOR j:=0 TO 1 DO
BEGIN
tlongint:=xmax-xmin+(2*pref_settings[pref_clipamt_id]);
tlongint:=ABS(GetRandWithCeiling(tlongint));
xyloc[j,i]:=WordRec(tlongint).lo+xmin-
pref_settings[pref_clipamt_id];
tlongint:=ymax-ymin+(2*pref_settings[pref_clipamt_id]);
tlongint:=ABS(GetRandWithCeiling(tlongint));
xyloc[j+2,i]:=Wordrec(tlongint).lo+xmin-
pref_settings[pref_clipamt_id];
END;
{ Clear the window }
EraseClient;
{ Select a pen }
tlongint:=ABS(GetRandWithCeiling(7));
i:=WordRec(tlongint).lo;
{ Get a device context }
HDevCont:=GetDC(HByteWin);
SelectObject(HDevCont,pens[i]);
{ Start timing }
StartStopWatch;
{ Draw lines }
FOR j:=0 TO lines_per_iter DO
BEGIN
MoveTo(HDevCont,xyloc[0,j],xyloc[2,j]);
LineTo(HDevCont,xyloc[1,j],xyloc[3,j]);
END;
{ Stop timing and accumulate }
StopStopWatch;
Inc(iterarray[line_test_id]);
AccumTiming(line_test_id);
{ Release the device context }
ReleaseDC(HByteWin,HDevCont);
END; { WHILE }
{ Delete the pens }
DeletePens;
{ Put menu back the way it was }
SetMenu(HByteWin,omenuhand);
DestroyMenu(menuhand);
END; { LineTest }
{ ******************* }
{ PolyGons benchmark }
PROCEDURE PolygonTest;
VAR
ppoints: ARRAY[0..polys_per_iter*9] OF TPoint;
npoints: ARRAY[0..polys_per_iter-1] OF Integer;
HDevCont: HDC; { Device context }
mypen: HPen; { Current drawing pen }
i: Integer; { Index }
tlongint: LongInt; { Temp long integer }
xmin, xmax: Integer; { X clipping bounds }
ymin, ymax: Integer; { Y clipping bounds }
HisRect: TRect; { Client rectangle }
xloc, yloc: Word; { Center points of polygon }
menuhand: HMenu; { Handle for menu }
omenuhand: HMenu; { Old menu handle }
BEGIN
{ Set up the proper menu }
menuhand:=LoadMenu(HInstance,'POLYMENU');
omenuhand:=GetMenu(HByteWin);
SetMenu(HByteWin,menuhand);
{ Make some pens }
MakePens;
{ Clear the timing arrays }
elapsedtsecarray[poly_test_id]:=0;
iterarray[poly_test_id]:=0;
GetClientRect(HByteWin,HisRect);
xmin:=HisRect.left-pref_settings[pref_clipamt_id];
ymin:=HisRect.top-pref_settings[pref_clipamt_id];
xmax:=HisRect.right+pref_settings[pref_clipamt_id];
ymax:=HisRect.bottom+pref_settings[pref_clipamt_id];
{ Begin the loop. Execute inner loops until the outer-loop }
{ number of seconds is satisfied. }
WHILE (elapsedtsecarray[poly_test_id] DIV 1000)<poly_secs DO
BEGIN
(**
** Build some polygons.
** This is an admittedly scary-looking algorithm that
** builds a guaranteed convex 8-sided [I think] polygon.
**)
FOR i:=0 TO polys_per_iter-1 DO
BEGIN
npoints[i]:=9; { All polygons have 9 endpoints }
tlongint:=xmax-xmin;
tlongint:=ABS(GetRandWithCeiling(tlongint));
xloc:=WordRec(tlongint).lo+xmin;
tlongint:=ymax-ymin;
tlongint:=ABS(GetRandWithCeiling(tlongint));
yloc:=WordRec(tlongint).lo+ymin;
ppoints[i*9].x:=xloc;
tlongint:=yloc-ymin;
tlongint:=ABS(GetRandWithCeiling(tlongint));
ppoints[i*9].y:=yloc-WordRec(tlongint).lo;
tlongint:=LMin(xmax-xloc,yloc-ymin);
tlongint:=ABS(GetRandWithCeiling(tlongint));
ppoints[i*9+1].x:=xloc+WordRec(tlongint).lo;
ppoints[i*9+1].y:=yloc-WordRec(tlongint).lo;
tlongint:=xmax-xloc;
tlongint:=ABS(GetRandWithCeiling(tlongint));
ppoints[i*9+2].x:=xloc+WordRec(tlongint).lo;
ppoints[i*9+2].y:=yloc;
tlongint:=LMin(ymax-yloc,xmax-xloc);
tlongint:=ABS(GetRandWithCeiling(tlongint));
ppoints[i*9+3].x:=xloc+WordRec(tlongint).lo;
ppoints[i*9+3].y:=yloc+WordRec(tlongint).lo;
tlongint:=ymax-yloc;
tlongint:=ABS(GetRandWithCeiling(tlongint));
ppoints[i*9+4].x:=xloc;
ppoints[i*9+4].y:=yloc+WordRec(tlongint).lo;
tlongint:=LMin(xloc-xmin,ymax-yloc);
tlongint:=ABS(GetRandWithCeiling(tlongint));
ppoints[i*9+5].x:=xloc-WordRec(tlongint).lo;
ppoints[i*9+5].y:=yloc+WordRec(tlongint).lo;
tlongint:=xloc-xmin;
tlongint:=ABS(GetRandWithCeiling(tlongint));
ppoints[i*9+6].x:=xloc-WordRec(tlongint).lo;
ppoints[i*9+6].y:=yloc;
tlongint:=Lmin(yloc-ymin,xloc-xmin);
tlongint:=ABS(GetRandWithCeiling(tlongint));
ppoints[i*9+7].x:=xloc-WordRec(tlongint).lo;
ppoints[i*9+7].y:=yloc-WordRec(tlongint).lo;
ppoints[i*9+8].x:=ppoints[i*9].x;
ppoints[i*9+8].y:=ppoints[i*9].y;
END;
{ Erase the window }
EraseClient;
{ Get a device context }
HDevCont:=GetDC(HByteWin);
SetPolyFillMode(HdevCont,Winding);
{ Select a pen }
tlongint:=ABS(GetRandWithCeiling(7));
i:=WordRec(tlongint).lo;
mypen:=SelectObject(HDevCont,pens[i]);
{ Select a brush }
tlongint:=ABS(GetRandWithCeiling(10));
SelectObject(HdevCont,GetStockObject(brush_style[tlongint]));
{ Start timing }
StartStopWatch;
{ Draw polygons }
PolyPolygon(HDevCont,ppoints,npoints,polys_per_iter-1);
{ Stop timing }
StopStopWatch;
{ Release the device context }
ReleaseDC(HByteWin,HDevCont);
{ Accumulate results }
Inc(iterarray[poly_test_id]);
AccumTiming(poly_test_id);
END; { WHILE }
{ Delete the pens }
DeletePens;
{ Put menu back the way it was }
SetMenu(HByteWin,omenuhand);
DestroyMenu(menuhand);
END; { PolygonTest }
{ ******************** }
{ Rectangles Benchmark }
PROCEDURE RectTest;
VAR
rpoints: ARRAY [0..3,0..rects_per_iter] OF Integer; { Rect. points }
mypen: HPen; { Current pen }
i: Integer; { Index }
tlongint: LongInt; { Temp. for long int. }
halfx: LongInt; { Half the allowed x range }
halfy: LongInt; { Half the allowed y range }
HDevCont: HDC; { Device context }
xmin, xmax: Integer; { X clipping bounds }
ymin, ymax: Integer; { Y clipping bounds }
HisRect: TRect; { Client rectangle }
menuhand: HMenu; { Handle for menu }
omenuhand: HMenu; { Old menu handle }
BEGIN
{ Set up the proper menu }
menuhand:=LoadMenu(HInstance,'RECTMENU');
omenuhand:=GetMenu(HByteWin);
SetMenu(HByteWin,menuhand);
{ Make some pens }
MakePens;
{ Clear the timing arrays }
elapsedtsecarray[rect_test_id]:=0;
iterarray[rect_test_id]:=0;
{ Determine the clipping bounds for this test. }
GetClientRect(HByteWin,HisRect);
xmin:=HisRect.left;
ymin:=HisRect.top;
xmax:=HisRect.right;
ymax:=HisRect.bottom;
halfx:=(xmax-xmin+(2*pref_settings[pref_clipamt_id]))
DIV 2;
halfy:=(ymax-ymin+(2*pref_settings[pref_clipamt_id]))
DIV 2;
{ Begin the loop. Execute inner loops until the outer-loop }
{ number of seconds is satisfied. }
WHILE (elapsedtsecarray[rect_test_id])/1000<rect_secs DO
BEGIN
{ Fill the array of rectangle points. }
{ rpoints[0,i],rpoints[1,i] = x,y of ULHC }
{ rpoints[2,i],rpoints[3,i] = x,y or LRHC }
FOR i:=0 TO rects_per_iter DO
BEGIN
tlongint:=ABS(GetRandWithCeiling(halfx));
rpoints[0,i]:=WordRec(tlongint).lo+xmin-
pref_settings[pref_clipamt_id];
tlongint:=ABS(GetRandWithCeiling(halfy));
rpoints[1,i]:=WordRec(tlongint).lo+ymin-
pref_settings[pref_clipamt_id];
tlongint:=ABS(GetRandWithCeiling(halfx));
rpoints[2,i]:=WordRec(tlongint).lo+((xmax-xmin) DIV 2);
tlongint:=ABS(GetRandWithCeiling(halfy));
rpoints[3,i]:=WordRec(tlongint).lo+((ymax-ymin) DIV 2);
END; { FOR }
{ Clear drawing area }
EraseClient;
{ Get a device context }
HDevCont:=GetDC(HByteWin);
{ Set the current brush to hollow }
SelectObject(HDevCont,GetStockObject(Hollow_Brush));
{ Select a pen }
tlongint:=ABS(GetRandWithCeiling(7));
i:=WordRec(tlongint).lo;
mypen:=SelectObject(HDevCont,pens[i]);
{ Start timing }
StartStopWatch;
{ Draw rectangles }
FOR i:=0 TO rects_per_iter DO
Rectangle(HDevCont,rpoints[0,i],rpoints[1,i],
rpoints[2,i],rpoints[3,i]);
{ Stop timing }
StopStopWatch;
{ Release DC }
ReleaseDC(HByteWin,HDevCont);
{ Accumulate results }
Inc(iterarray[rect_test_id]);
AccumTiming(rect_test_id);
END; { WHILE }
{ Delete the pens }
DeletePens;
{ Put menu back the way it was }
SetMenu(HByteWin,omenuhand);
DestroyMenu(menuhand);
END; { RectTest }
{ ******************** }
{ Ellipses Benchmark }
PROCEDURE EllipseTest;
VAR
rpoints: ARRAY [0..3,0..ellps_per_iter] OF Integer; { Rect. points }
mypen: HPen; { Current pen }
i: Integer; { Index }
tlongint: LongInt; { Temp. for long int. }
halfx: LongInt; { Half the allowed x range }
halfy: LongInt; { Half the allowed y range }
HDevCont: HDC; { Device context }
xmin, xmax: Integer; { X clipping bounds }
ymin, ymax: Integer; { Y clipping bounds }
HisRect: TRect; { Client rectangle }
menuhand: HMenu; { Handle for menu }
omenuhand: HMenu; { Old menu handle }
BEGIN
{ Set up the proper menu }
menuhand:=LoadMenu(HInstance,'ELLMENU');
omenuhand:=GetMenu(HByteWin);
SetMenu(HByteWin,menuhand);
{ Make some pens }
MakePens;
{ Clear the timing arrays }
elapsedtsecarray[arce_test_id]:=0;
iterarray[arce_test_id]:=0;
{ Determine the clipping bounds for this test. }
GetClientRect(HByteWin,HisRect);
xmin:=HisRect.left;
ymin:=HisRect.top;
xmax:=HisRect.right;
ymax:=HisRect.bottom;
halfx:=(xmax-xmin+(2*pref_settings[pref_clipamt_id]))
DIV 2;
halfy:=(ymax-ymin+(2*pref_settings[pref_clipamt_id]))
DIV 2;
{ Begin the loop. Execute inner loops until the outer-loop }
{ number of seconds is satisfied. }
WHILE (elapsedtsecarray[arce_test_id] DIV 1000)<arce_secs DO
BEGIN
{ Fill the array of rectangle points. }
{ rpoints[0,i],rpoints[1,i] = x,y of ULHC }
{ rpoints[2,i],rpoints[3,i] = x,y or LRHC }
FOR i:=0 TO ellps_per_iter DO
BEGIN
tlongint:=ABS(GetRandWithCeiling(halfx));
rpoints[0,i]:=WordRec(tlongint).lo+xmin-
pref_settings[pref_clipamt_id];
tlongint:=ABS(GetRandWithCeiling(halfy));
rpoints[1,i]:=WordRec(tlongint).lo+ymin-
pref_settings[pref_clipamt_id];
tlongint:=ABS(GetRandWithCeiling(halfx));
rpoints[2,i]:=WordRec(tlongint).lo+((xmax-xmin) DIV 2);
tlongint:=ABS(GetRandWithCeiling(halfy));
rpoints[3,i]:=WordRec(tlongint).lo+((ymax-ymin) DIV 2);
END; { FOR }
{ Clear drawing area }
EraseClient;
{ Get a device context }
HDevCont:=GetDC(HByteWin);
{ Set the current brush to hollow }
SelectObject(HDevCont,GetStockObject(Hollow_Brush));
{ Select a pen }
tlongint:=ABS(GetRandWithCeiling(7));
i:=WordRec(tlongint).lo;
mypen:=SelectObject(HDevCont,pens[i]);
{ Start timing }
StartStopWatch;
{ Draw ellipses }
FOR i:=0 TO ellps_per_iter DO
Ellipse(HDevCont,rpoints[0,i],rpoints[1,i],
rpoints[2,i],rpoints[3,i]);
{ Stop timing }
StopStopWatch;
{ Release DC }
ReleaseDC(HByteWin,HDevCont);
{ Accumulate results }
Inc(iterarray[arce_test_id]);
AccumTiming(arce_test_id);
END; { WHILE }
{ Delete the pens }
DeletePens;
{ Put menu back the way it was }
SetMenu(HByteWin,omenuhand);
DestroyMenu(menuhand);
END; { RectTest }
(*****************
** BITMAP Test **
*)
PROCEDURE BitbltTest;
VAR
xdest: ARRAY [0..bmap_points] OF Integer; { Dest x coordinates }
ydest: ARRAY [0..bmap_points] OF Integer; { Dest y coordinates }
HDevCont: HDC; { Device context }
HMDevCont: HDC; { Memory device context }
bithand: HBitmap; { Bitmap handle }
i: Word; { Index }
tlongint: Longint; { Temporary long }
HisRect: TRect; { Client rectangle }
xmin, xmax: Integer; { X clipping bounds }
ymin, ymax: Integer; { Y clipping bounds }
menuhand: HMenu; { Handle for menu }
omenuhand: HMenu; { Old menu handle }
BEGIN
{ Set up the proper menu }
menuhand:=LoadMenu(HInstance,'BITMENU');
omenuhand:=GetMenu(HByteWin);
SetMenu(HByteWin,menuhand);
{ Clear the timing arrays }
elapsedtsecarray[bitblt_test_id]:=0;
iterarray[bitblt_test_id]:=0;
{ Determine clipping bounds for this test }
GetClientRect(HByteWin,HisRect);
xmin:=HisRect.left;
ymin:=HisRect.top;
xmax:=HisRect.right-bmap_size;
ymax:=HisRect.bottom-bmap_size;
{ Load the bitmap }
bithand:=LoadBitMap(HInstance,'BERM');
{ Begin the loop...execute inner loop until time expires }
WHILE (elapsedtsecarray[bitblt_test_id] DIV 1000)<bitblt_secs DO
BEGIN
{ Generate a random collection of destination points }
FOR i:=0 TO bmap_points DO
BEGIN
tlongint:=xmax-xmin;
tlongint:=ABS(GetRandWithCeiling(tlongint))+xmin;
xdest[i]:=WordRec(tlongint).lo;
tlongint:=ymax-ymin;
tlongint:=ABS(GetRandWithCeiling(tlongint))+ymin;
ydest[i]:=WordRec(tlongint).lo;
END;
{ Get a context }
HDevCont:=GetDC(HByteWin);
{ Clear the client rectangle }
EraseClient;
{ Get a memory context }
HMDevCont:=CreateCompatibleDC(HDevCont);
{ Put our bitmap in the memory context }
SelectObject(HMDevCont,bithand);
{ Start timing }
StartStopWatch;
{ Copy bitmap into first screen slot }
BitBlt(HDevCont,xdest[0],ydest[0],bmap_size,bmap_size,
HMDevCont,0,0,SrcCopy);
{ Loop...copying bitmap from source to destination }
FOR i:=1 TO bmap_points DO
BitBlt(HDevCont,xdest[i],ydest[i],bmap_size,bmap_size,
HDevCont,xdest[i-1],ydest[i-1],SrcCopy);
{ Stop timing}
StopStopWatch;
{ Release context }
ReleaseDC(HByteWin,HDevCont);
DeleteDC(HMDevCont);
{ Accumulate results }
Inc(iterarray[bitblt_test_id]);
AccumTiming(bitblt_test_id);
END;
{ Dump the bitmap }
DeleteObject(bithand);
{ Put menu back the way it was }
SetMenu(HByteWin,omenuhand);
DestroyMenu(menuhand);
END; { BitmapTest }
(********************
** Text benchmark **
*)
PROCEDURE TextTest;
VAR
locs: ARRAY[1..text_per_iter] of TRect; { Coords for text }
HisRect: TRect; { Client rectangle }
xmin, xmax: Integer; { X clipping bounds }
ymin, ymax: Integer; { Y clipping bounds }
myfont: ARRAY[0..2] of HFont; { Logical font record }
mytext: ARRAY[0..80] of Char; { Local sentence }
mytextlen: Integer; { Length of string }
mytexthi: Integer; { Height of string }
mytextwide: Integer; { Width of string }
textxmax: Integer; { Max text start x }
textymax: Integer; { Max text start y }
rectxmin: Integer; { Min rectangle x }
rectymin: Integer; { Min rectangly y }
i: Integer; { Index and stuff }
tlongint: Longint; { Temp long integer }
HDevCont: HDC; { Device context }
redval, greenval, blueval: Byte; { Colors }
myformat: Word; { Format }
menuhand: HMenu; { Handle for menu }
omenuhand: HMenu; { Old menu handle }
BEGIN
{ Set up the proper menu }
menuhand:=LoadMenu(HInstance,'TEXTMENU');
omenuhand:=GetMenu(HByteWin);
SetMenu(HByteWin,menuhand);
{ Clear the timing arrays }
elapsedtsecarray[texto_test_id]:=0;
iterarray[texto_test_id]:=0;
elapsedtsecarray[dtext_test_id]:=0;
iterarray[dtext_test_id]:=0;
{ Determine the rectangle bounds }
GetClientRect(HByteWin,HisRect);
xmin:=HisRect.left;
ymin:=HisRect.top;
xmax:=HisRect.right;
ymax:=HisRect.bottom;
{ Create some logical fonts }
{ Height=10, Width=8, Normal, Not Italic, Not Underlined,
No Strikeout, ANSI characterset, Default Precision,
default Clip Precision, Default Quality,Default Pitch,
System Typeface }
myfont[0]:=CreateFont(10,8,0,0,400,0,0,0,ANSI_CHARSET,
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, DEFAULT_PITCH, 'System');
{ Height=20, Width=16, Bold, Not Italic, Not Underlined,
No Strikeout, ANSI characterset, default precision,
default clip precision, default quality,Default Pitch,
Helvetica typeface }
myfont[1]:=CreateFont(20,16,0,0,700,0,0,0,ANSI_CHARSET,
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, DEFAULT_PITCH,'Helv');
{ Height=16, width=10, Normal, Italic, Not Underlined,
No strikeout, ANSI characterset, default precision,
default clip precision, default quality, default pitch,
Courier typeface }
myfont[2]:=CreateFont(16,10,0,0,400,1,0,0,ANSI_CHARSET,
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, DEFAULT_PITCH,'Script');
{ Begin the loop...execute inner loop until time expires }
WHILE (elapsedtsecarray[texto_test_id] DIV 1000)<text_secs DO
BEGIN
{ Select a sentence into the local variable }
tlongint:=5;
tlongint:=ABS(GetRandWithCeiling(tlongint));
StrPCopy(mytext,bench_strs[tlongint]);
mytextlen:=StrLen(mytext);
{ Get a context }
HDevCont:=GetDC(HByteWin);
{ Set the text color }
tlongint:=RandNum(0);
i:=WordRec(tlongint).lo;
redval:=ByteRec(i).lo;
tlongint:=RandNum(0);
i:=WordRec(tlongint).lo;
greenval:=ByteRec(i).lo;
tlongint:=RandNum(0);
i:=WordRec(tlongint).lo;
blueval:=ByteRec(i).lo;
SetTextColor(HDevCont,RGB(redval,greenval,blueval));
{ Set the background }
SetBkColor(HDevCont,RGB(0,0,0));
IF ((RandNum(0) AND 1) = 1) THEN
SetBkMode(HDevCont,Opaque)
ELSE
SetBkMode(HDevCont,Transparent);
{ Randomly pick a logical font }
tlongint:=ABS(GetRandWithCeiling(2));
SelectObject(HDevCont,myfont[tlongint]);
{ Determine the range of allowed origin coordinates }
tlongint:=GetTextExtent(HDevCont,mytext,mytextlen);
mytexthi:=WordRec(tlongint).hi;
mytextwide:=WordRec(tlongint).lo;
textxmax:=xmax-mytextwide-1;
IF textxmax<0 THEN
textxmax:=xmin+10;
textymax:=ymax-mytexthi-1;
IF textymax<0 THEN
textymax:=ymin+10;
{ Randomly select an array of starting coordinates }
FOR i:=1 TO text_per_iter DO
BEGIN
tlongint:=textxmax-xmin;
tlongint:=ABS(GetRandWithCeiling(tlongint))+xmin;
locs[i].left:=tlongint;
tlongint:=textymax-ymin;
tlongint:=ABS(GetRandWithCeiling(tlongint))+ymin;
locs[i].top:=tlongint;
END; { FOR }
{ Clear the client rectangle }
EraseClient;
{ Start timing }
StartStopWatch;
{ Step through the array of coordinates, display sentence }
FOR i:=1 to text_per_iter DO
TextOut(HDevCont,locs[i].left,locs[i].top,@mytext,mytextlen);
{ Stop timing}
StopStopWatch;
{ Release context }
ReleaseDC(HByteWin,HDevCont);
{ Accumulate results }
Inc(iterarray[texto_test_id]);
AccumTiming(texto_test_id);
END; { WHILE }
{ Begin the loop...execute inner loop until time expires }
WHILE (elapsedtsecarray[dtext_test_id] DIV 1000)<text_secs DO
BEGIN
{ Select a sentence into the local variable }
tlongint:=5;
tlongint:=ABS(GetRandWithCeiling(tlongint));
StrPCopy(mytext,bench_strs[tlongint]);
mytextlen:=StrLen(mytext);
{ Get a context }
HDevCont:=GetDC(HByteWin);
{ Set the text color }
tlongint:=RandNum(0);
i:=WordRec(tlongint).lo;
redval:=ByteRec(i).lo;
tlongint:=RandNum(0);
i:=WordRec(tlongint).lo;
greenval:=ByteRec(i).lo;
tlongint:=RandNum(0);
i:=WordRec(tlongint).lo;
blueval:=ByteRec(i).lo;
SetTextColor(HDevCont,RGB(redval,greenval,blueval));
{ Set the background }
SetBkColor(HDevCont,RGB(0,0,0));
IF ((RandNum(0) AND 1) = 1) THEN
SetBkMode(HDevCont,Opaque)
ELSE
SetBkMode(HDevCont,Transparent);
{ Randomly pick a logical font }
tlongint:=ABS(GetRandWithCeiling(2));
SelectObject(HDevCont,myfont[tlongint]);
{ Determine the range of allowed origin coordinates }
tlongint:=GetTextExtent(HDevCont,mytext,mytextlen);
mytexthi:=WordRec(tlongint).hi;
mytextwide:=WordRec(tlongint).lo;
textxmax:=xmax-mytextwide-1;
IF textxmax<0 THEN
textxmax:=xmin+10;
textymax:=ymax-mytexthi-1;
IF textymax<0 THEN
textymax:=ymin+10;
{ Determine range of allowed rectangle extents }
rectxmin:=mytextwide DIV 3;
rectymin:=mytexthi DIV 3;
{ Create array of random rectangles }
FOR i:=1 TO text_per_iter DO
BEGIN
tlongint:=textxmax-xmin;
tlongint:=ABS(GetRandWithCeiling(tlongint))+xmin;
locs[i].left:=WordRec(tlongint).lo;
tlongint:=textymax-ymin;
tlongint:=ABS(GetRandWithCeiling(tlongint))+ymin;
locs[i].top:=WordRec(tlongint).lo;
tlongint:=xmax-rectxmin;
tlongint:=ABS(GetRandWithCeiling(tlongint))+rectxmin;
locs[i].right:=WordRec(tlongint).lo;
tlongint:=ymax-rectymin;
tlongint:=ABS(GetRandWithCeiling(tlongint))+rectymin;
locs[i].bottom:=WordRec(tlongint).lo;
END;
{ Select a format }
tlongint:=RandNum(0);
IF ((tlongint AND 1)=1) THEN
myformat:=DT_LEFT
ELSE
myformat:=DT_RIGHT;
IF((tlongint AND 2)=2) THEN
myformat:=myformat OR DT_TOP
ELSE
myformat:=myformat OR DT_CENTER;
myformat:=myformat OR DT_WORDBREAK;
{ Clear the client rectangle }
EraseClient;
{ Start timing }
StartStopWatch;
{ Step through the array of coordinates, display sentence }
FOR i:=1 to text_per_iter DO
DrawText(HdevCont,@mytext,mytextlen,locs[i],myformat);
{ Stop timing}
StopStopWatch;
{ Release context }
ReleaseDC(HByteWin,HDevCont);
{ Accumulate results }
Inc(iterarray[dtext_test_id]);
AccumTiming(dtext_test_id);
END; { WHILE }
{ We don't need the logical fonts anymore }
FOR i:=0 TO 2 DO
DeleteObject(myfont[i]);
{ Put menu back the way it was }
SetMenu(HByteWin,omenuhand);
DestroyMenu(menuhand);
END;
(**********************
** Sequential file I/O
*)
PROCEDURE SFile_IO;
VAR
fhandle: Integer; { File handle }
openbuf: TOFStruct; { Open file buffer }
fbuff: ARRAY [0..8191] OF Char; { I/O buffer }
offset: LongInt; { File offset }
i: LongInt; { Index }
j: Integer; { Another index }
outstr: Array [0..80] of Char; { message to display }
outstrlen: Integer; { need to know how long it is }
BEGIN
{ erase the screen and let user know what we are doing }
InitBenchDisplay;
strPCopy( @outstr, 'Starting sequential file i/o test.');
outstrlen := StrLen( @outstr );
DisplayBenchLine( @outstr, outstrlen );
StrPCopy( @outstr, 'Creating test file.');
outstrlen := StrLen( @outstr );
DisplayBenchLine( @outstr, outstrlen );
{ Try to create the workfile. If we can do it, fine. }
{ Otherwise, tell the user we failed, delete the file, }
{ and bail out. }
fhandle:=Openfile('BYTE.TMP',openbuf,of_Create);
IF fhandle=-1 THEN
BEGIN
{ Tell of failure }
EXIT;
END;
{ initialize the buffer with write values. }
FOR i:=0 TO 8191 DO
fbuff[i]:='B';
{ initialize the file for output }
FOR i:=1 TO sfilesize DIV 1000 DO
BEGIN
j:=_lwrite(fhandle,@fbuff,1000);
IF j=-1 THEN
BEGIN
{ Failed to write the file...tell user }
_lclose(fhandle);
Openfile('BYTE.TMP',openbuf,of_Delete);
EXIT;
END;
END; { FOR }
StrPCopy( @outstr, 'Starting sequential file read test.' );
outstrlen := StrLen( @outstr );
DisplayBenchLine( @outstr, outstrlen );
{ really start the test }
elapsedtsecarray[sfio_test_id] := 0;
iterarray[sfio_test_id] := 1; { we're only doing this 1x}
StartStopWatch;
{ READ loop. Pass through the file 4 times, once for }
{ each record length selected in configuration. }
FOR i:=0 TO 3 DO
BEGIN
_llseek(fhandle,0,0); { Rewind }
offset:=0;
WHILE offset+sfilereclen[i]<=sfilesize DO
BEGIN
_lread(fhandle,@fbuff,sfilereclen[i]);
offset:=offset+sfilereclen[i];
END; { WHILE }
END; { FOR }
{ test half over. stop the clock. Tell people we're working. Restart clock }
StopStopWatch;
AccumTiming( sfio_test_id );
StrPCopy( @outstr, 'Starting sequential file write test.' );
outstrlen := StrLen( @outstr );
DisplayBenchLine( @outstr, outstrlen );
StartStopWatch;
{ WRITE loop. Pass through the file 4 times, writing }
{ records in chunks same as the READ loop. }
FOR i:=0 TO 3 DO
BEGIN
_llseek(fhandle,0,0); { Rewind }
offset:=0;
WHILE offset+sfilereclen[i]<=sfilesize DO
BEGIN
_lwrite(fhandle,@fbuff,sfilereclen[i]);
offset:=offset+sfilereclen[i];
END; { WHILE }
END; { FOR }
{ test over -- pickup the timings.}
StopStopWatch;
AccumTiming( sfio_test_id );
{ All done. Record results and delete the file. }
_lclose(fhandle);
Openfile('BYTE.TMP',openbuf,of_Delete);
EraseClient;
END;
{ given an offset, return a uniqe file name }
PROCEDURE gfName( offset : Integer; VAR retStr:FileName );
VAR
s: FileName;
BEGIN
StrPCopy( retStr, 'BYTEDAT.' );
Str( offset, s );
StrCat(retStr, s);
END;
{********************
** Create files for random file i/o.
** Accumulate the number of bytes written to the files.
*}
PROCEDURE createFiles( fnum:integer; VAR myMax: LongInt );
CONST
wvector: ARRAY[0..19] of LongInt = ( 4000, 1000, 500, 2800, 2500,
1400, 8000, 8800, 300, 21111,
2000, 6000, 200, 48800, 1300,
9870, 3000, 2816, 8660, 127 );
VAR
i: INTEGER;
s: FileName;
fhandle: Integer; { File handle }
openbuf: TOFStruct; { Open file buffer }
nb : Integer; { number of bytes to write }
j : Integer;
BEGIN
gfName( fnum, s );
fhandle := Openfile( @s, openbuf, of_Create);
IF fhandle = -1 THEN
BEGIN
{ Tell of failure }
EXIT;
END;
nb := wvector[ fnum ];
j := _lwrite( fhandle, BigFileBuff^, nb );
IF j=-1 THEN
BEGIN
{ Failed to write the file...tell user }
_lclose(fhandle);
Openfile( @s, openbuf, of_Delete);
EXIT;
END;
myMax := myMax + nb;
_lclose( fhandle );
END;
{********************
** Delete all files from random file i/o test.
*}
PROCEDURE DeleteAllFiles;
VAR
i: INTEGER;
s: FileName;
fhandle: Integer; { File handle }
openbuf: TOFStruct; { Open file buffer }
BEGIN
FOR i := 0 to 19
do begin
gfName( i, s );
fhandle := Openfile( @s, openbuf, of_Delete );
end;
END;
{** Opens a file and appends the appropriate number of bytes.
**
**}
PROCEDURE appendFiles( fnum:integer; VAR myMax: LongInt );
CONST
wvector: ARRAY[0..19] of LongInt = ( 1200, 2030, 31111, 3400, 9099,
2075, 7000, 400, 2200, 2700,
2360, 1495, 5960, 3430, 70,
3600, 8900, 1233, 4000, 1000 );
VAR
i: INTEGER;
s: FileName;
fhandle: Integer; { File handle }
openbuf: TOFStruct; { Open file buffer }
nb : Integer; { number of bytes to write }
j : Integer;
BEGIN
gfName( fnum, s );
fhandle := OpenFile( s, openbuf, of_Write );
_llseek( fhandle, 0, 2 ); { seek to end of file}
nb := wvector[ fnum ];
j:=_lwrite( fhandle, BigFileBuff^, nb );
myMax := myMax + nb;
_lclose( fHandle );
END;
{********************
** FileSize
** Determine the size of an already-open file.
*}
FUNCTION FileSize( fh: Integer ) : LongInt;
VAR
pos: LongInt;
BEGIN
Pos := _llseek( fh, 0, 1 ); { get current file position }
FileSize := _llseek( fh, 0, 2 ); { seek to end of file -- return new position }
_llseek( fh, Pos, 0 ); { seek back to original position }
END; {FileSize}
{*********************
** ll_seekwrite
** seek to offset from beginning of file.
** then write nb bytes from the global buffer
*}
PROCEDURE ll_seekwrite( fh:Integer; offset:LongInt; nb:LongInt );
BEGIN
_llseek( fh, offset, 0 );
_lwrite(fh, BigFileBuff^, nb );
END;
{*********************
** ll_seekread
** seek to offset from beginning of file.
** then read nb bytes from the global buffer
*}
PROCEDURE ll_seekread( fh: Integer; offset: LongInt; nb: LongInt );
BEGIN
_llseek( fh, offset, 0 );
_lread( fh, BigFileBuff^, nb );
END;
(********************
** Random file I/O
*)
PROCEDURE RFile_IO( doTime: LongInt );
CONST
MaxRandomIOBytes = 10000000; { don't exceed 10 Mbytes of output }
VAR
fileResult: Boolean;
l : LongInt;
i : Integer;
myMax : LongInt; { how many bytes of throughput? }
avg : LongInt; { number of bytes read on a cycle }
n : Integer;
nb : LongInt; { number of bytes to read/write }
fh : Integer; { file handle }
str : FileName; { full filename }
flen : LongInt; { file length }
offset : LongInt; { offset into file }
count : Integer; { debugging counter }
rbytes : LongInt; { number of bytes read }
wbytes : LongInt; { number of bytes written }
outstr: Array [0..80] of Char; { message to display }
outstrlen: Integer; { need to know how long it is }
BEGIN
{ See if we have enough free space. If not, bail
out. We set our minimum to 6 MB }
InitBenchDisplay;
strPCopy( @outstr, 'Starting random file i/o test.');
outstrlen := StrLen( @outstr );
DisplayBenchLine( @outstr, outstrlen );
{ create the global buffer }
New( BigFileBuff ); {rgac? fix possible run-time}
{ initialize the global buffer }
for l:= 0 to 39999
do begin
BigFileBuff^[l] := 'A';
end;
{ Initialize the maximum }
myMax := 0;
StrPCopy( @outstr, 'Creating test files.');
outstrlen := StrLen( @outstr );
DisplayBenchLine( @outstr, outstrlen );
{ create the files }
for i:= 0 to 19
do begin
createFiles( i, myMax );
end;
{ extend the files }
for i := 0 to 19
do begin
appendFiles( i, myMax );
end;
myMax := 0;
{ initialize random number generator and misc variables }
Randnum(13);
elapsedtsecarray[rfio_test_id] := 0;
iterarray[rfio_test_id] := 1;
avg := 0;
rbytes := 0;
wbytes := 0;
DelaySeconds( 5 ); { let buffers catch up from last test }
StrPCopy( @outstr, 'Starting Test:');
outstrlen := StrLen( @outstr );
DisplayBenchLine( @outstr, outstrlen );
count := 0;
{ run the test }
{ for each pass, do 3 reads and 1 write }
repeat
avg := 0;
for i := 0 to 2
do begin
n := Abs( GetRandWithCeiling(19) );
gfName( n, str );
fh := _lopen( str, of_Read );
flen := fileSize( fh );
offset := Abs( GetRandWithCeiling( flen ) );
flen := flen - offset;
if( flen <= 0 )
then begin
flen := 1;
end;
if( flen > 32000 ) then
begin
nb := 32000;
end else
begin
nb := flen;
end;
nb := Abs( GetRandWithCeiling( nb ) );
{ AHA! the actual test! }
StartStopWatch;
ll_seekread( fh, offset, nb );
StopStopWatch;
{ accumulate the timing information }
AccumTiming( rfio_test_id );
avg := avg + nb;
rbytes := rbytes + nb;
{ close the file -- we're done }
_lclose( fh );
end; {for loop}
n := Abs( GetRandWithCeiling( 19 ) );
n := Abs( GetRandWithCeiling( 19 ) );
gfName( n, str );
fh := _lopen( str, of_Write );
flen := fileSize( fh );
offset := Abs( GetRandWithCeiling( flen ) );
nb := Trunc(avg / 3);
if( offset + nb > flen )
then begin
myMax := myMax + offset + nb - flen;
if( myMax > MaxRandomIOBytes )
then begin
exit
end;
end;
StartStopWatch;
ll_seekwrite( fh, offset, nb );
StopStopWatch;
AccumTiming( rfio_test_id );
wbytes := wbytes + nb;
_lclose( fh );
Inc(count);
until( elapsedtsecarray[ rfio_test_id ] > doTime );
totalRandomIOBytes := rbytes + wbytes;
{ the tests are over, clean up the mess we've left }
StrPCopy( @outstr, 'Deleting Files.');
outstrlen := StrLen( @outstr );
DisplayBenchLine( @outstr, outstrlen );
{ zap the files }
DeleteAllFiles;
{zap the memory }
Dispose( BigFileBuff );
END;
{***************************
** Add logfile header to output
**
** If toFile is true -- just send the data the log file.
** If tofile is false -- just send the data to the screen.
** n.b. We never send the information to both places.
*}
PROCEDURE logfileHeader( toFile: Boolean );
VAR
outstr: Array [0..81] of Char;
tempstr: Array [0..81] of Char;
theHDC: HDC;
outlen: Integer;
tempWord: Word;
tempInt: Integer;
tempLInt: LongInt;
tempLInt2:LongInt;
year : Word;
month : Word;
day : Word;
doweek: Word;
hour : Word;
minute: Word;
second: Word;
sec100: Word;
BEGIN
StrCopy( outstr, 'File: ' );
StrPCopy( tempstr, logFileName );
StrCat( outstr, tempstr );
if toFile
then begin
Writeln( logFile, outstr );
end
else begin
outLen := StrLen( outstr );
DisplayBenchLine( outstr, outLen );
end;
GetDate( year, month, day, doweek );
StrCopy( outstr, 'Test run on: ' );
Str( month, tempstr );
StrCat( tempstr, '/' );
StrCat( outstr, tempstr );
Str( day, tempstr );
StrCat( tempstr, '/' );
StrCat( outstr, tempstr );
Str( year, tempstr );
StrCat( outstr, tempstr );
StrCat( outstr, ' at: ' );
GetTime( hour, minute, second, sec100 );
Str( hour, tempstr );
StrCat( outstr, tempstr );
StrCat( outstr, ':' );
if( minute < 10 )
then begin
StrCat( outstr, '0' );
end;
Str( minute, tempstr );
StrCat( outstr, tempstr );
if toFile
then begin
Writeln( logFile, outstr );
end
else begin
outLen := StrLen( outstr );
DisplayBenchLine( outstr, outLen );
end;
tempWord := GetVersion;
StrCopy( outstr, 'Windows Version: ' );
Str( Lo(tempWord), tempstr );
StrCat( outstr, tempstr );
StrCat( outstr, '.' );
Str( Hi(tempWord), tempstr);
StrCat( outstr, tempstr );
if toFile
then begin
Writeln( logFile, outstr );
end
else begin
outLen := StrLen( outstr );
DisplayBenchLine( outstr, outLen );
end;
tempInt := GetSystemMetrics( sm_Debug );
StrCopy( outstr, 'Debug version of Windows is ' );
if( 0 = tempInt )
then StrCat( outstr, 'not ' );
StrCat( outstr, 'installed.' );
if toFile
then begin
Writeln( logFile, outstr );
end
else begin
outLen := StrLen( outstr );
DisplayBenchLine( outstr, outLen );
end;
StrCopy( outstr, 'Screen width is: ' );
tempInt := GetSystemMetrics( sm_CXScreen );
Str( tempInt, tempStr );
StrCat( outstr, tempStr );
StrCat( outstr, ' pixels wide by ' );
tempInt := GetSystemMetrics( sm_CYScreen );
Str( tempInt, tempStr );
StrCat( outstr, tempStr );
StrCat( outstr, ' pixels high.' );
if toFile
then begin
Writeln( logFile, outstr );
end
else begin
outLen := StrLen( outstr );
DisplayBenchLine( outstr, outLen );
end;
tempLInt := GlobalCompact( 0 );
tempLInt := templint div 1024;
Str( tempLInt, outstr );
StrCat( outstr, ' Kbytes free in global heap.' );
if toFile
then begin
Writeln( logFile, outstr );
end
else begin
outLen := StrLen( outstr );
DisplayBenchLine( outstr, outLen );
end;
{ theHDC := GetDC( HByteWin );
tempInt := GetDeviceCaps( theHDC, BitsPixel );
StrCopy( outstr, 'Bit depth is ' );
Str( tempInt, tempstr );
StrCat( outstr, tempstr );
StrCat( outstr, ' bits per pixel.' );
if toFile
then begin
Writeln( logFile, outstr );
end
else begin
outLen := StrLen( outstr );
DisplayBenchLine( outstr, outLen );
end;
why is bit depth 1 pixel? }
END;
(***************************
** Display benchmark results
**
** doLog indicates whether the information should be written to the named file.
** oldResults indicates whether we show currently selected tests, or all tests
** with results.
** n.b. test results are not cleared between passes.
****************************)
PROCEDURE DisplayResults( doLog : Boolean; oldResults : Boolean );
VAR
i: Integer; { Loop index }
outstr: Array [0..80] of Char; { Output string }
outstrlen: Integer; { Output string length }
valstr: Array [0..20] of Char; { For holding values }
numer: Real; { Used in calculations }
denom: Real; { Same as above }
result: Real; { Results figure }
dtemp: Real; { For temporary results }
BEGIN
if( doLog ) { do we want to output to logfile? }
then begin
Assign( logFile, logFileName );
Rewrite( logfile );
logfileHeader(TRUE);
end;
InitBenchDisplay;
StrCopy( outstr, ' TEST RESULTS' );
outstrlen := StrLen( outstr );
DisplayBenchLine( outstr, outstrlen );
{ Examine the do_test_flags[] array to determine which tests
were executed. Produce a line of text for each one. }
FOR i:=1 TO max_num_tests DO
BEGIN
StrPCopy( @outstr, '' );
IF ( TRUE = do_test_flags[i] ) OR (TRUE = oldResults)
THEN BEGIN
{ only process tests for which time has elapsed.
takes care of showing old test results which have not actually been run!
}
if( elapsedtsecarray[i] > 0 )
then begin
{ Begin building the output string. }
StrPCopy(@outstr,test_name[i]);
numer:=iterarray[i];
denom:=elapsedtsecarray[i];
result := 0; {consider the case where denom is 0}
if( denom > 0 )
then begin
result:=( numer/denom) * 1000;
end;
CASE i OF
pixel_test_id:
BEGIN
dtemp:=pixels_per_iter;
result:=result * dtemp; { Pixels per second }
Str(result:10:2,valstr);
StrCat(@outstr,@valstr);
StrCat(@outstr,' pix per sec')
END;
line_test_id:
BEGIN
dtemp:=lines_per_iter;
result:=result * dtemp; { Lines per second }
Str(result:10:2,valstr);
StrCat(@outstr,@valstr);
StrCat(@outstr,' lines per sec');
END;
rect_test_id:
BEGIN
dtemp:=rects_per_iter;
result:=result * dtemp; { Rectangles per second }
Str(result:10:2,valstr);
StrCat(@outstr,@valstr);
StrCat(@outstr,' rects per sec');
END;
poly_test_id:
BEGIN
dtemp:=polys_per_iter;
result:=result * dtemp; { Polygons per second }
Str(result:10:2,valstr);
StrCat(@outstr,@valstr);
StrCat(@outstr,' polys per sec');
END;
arce_test_id:
BEGIN
dtemp:=ellps_per_iter;
result:=result * dtemp; { Ellipses per second }
Str(result:10:2,valstr);
StrCat(@outstr,@valstr);
StrCat(@outstr,' ellps per sec');
END;
bitblt_test_id:
BEGIN
dtemp:=bmap_points;
result:=result * dtemp; { Bitblt ops per second }
Str(result:10:2,valstr);
StrCat(@outstr,@valstr);
StrCat(@outstr,' bitblts per sec');
END;
lmem_test_id:
BEGIN
dtemp := iterarray[lmem_test_id];
result := dtemp / elapsedtsecarray[lmem_test_id]; {ms}
result := result * 1000; {sec}
Str( result:10:2, valstr );
StrCat( @outstr, @valstr );
StrCat( @outstr, ' iterations per sec' );
END;
gmem_test_id:
BEGIN
dtemp := iterarray[gmem_test_id];
result := dtemp / elapsedtsecarray[gmem_test_id]; {ms}
result := result * 1000; {sec}
Str( result:10:2, valstr );
StrCat( @outstr, @valstr );
StrCat( @outstr, ' iterations per sec' );
END;
sfio_test_id:
BEGIN
dtemp := (sfio_bytes_per_iter * numer) / 1024; {bytes -> Kbytes}
result := dtemp * result; {Kbytes / second}
Str( result:10:2, valstr );
StrCat( @outstr, @valstr );
StrCat( @outstr, ' Kbytes per sec' );
END;
rfio_test_id:
BEGIN
dtemp := (totalRandomIoBytes * result) / 1024;
Str( dtemp:10:2, valstr );
StrCat( @outstr, @valstr );
StrCat( @outstr, ' Kbytes per sec' );
END;
texto_test_id:
BEGIN
dtemp:=text_per_iter;
result:=result * dtemp; { Textout lines per second }
Str(result:10:2,valstr);
StrCat(@outstr,@valstr);
StrCat(@outstr,' TextOut ips ');
END;
dtext_test_id:
BEGIN
dtemp:=text_per_iter;
result:=result * dtemp; { Drawtext lines per second }
Str(result:10:2,valstr);
StrCat(@outstr,@valstr);
StrCat(@outstr,' Drawtext ips');
END;
END; { CASE }
{ Display one line of results }
outstrlen:=StrLen(@outstr);
if( outstrlen > 0 )
then begin
DisplayBenchLine(@outstr, outstrlen );
{ See if we also need to send to output file. }
if( doLog )
then begin
Writeln( logFile, outstr );
end;
end; {string has content }
END; { if time has elapsed }
END;
END; { FOR }
CloseBenchDisplay;
{ close file if we were writing to one. }
if( doLog )
then begin
Close( logFile );
end;
END; { DisplayResults }
(***************************************************
** Right justify a string. This has the effect of
** padding the string on the left with blanks until
** the string fills out the field width.
*)
PROCEDURE RightJustifyString( fieldwidth : Integer; strng : PChar);
VAR
tempstr: ARRAY[0..60] of Char;
BEGIN
{ Add fieldwidth-length(strng) bytes to our
temp string. Note that if strng is already
longer than fieldwidth, we gotta truncate. }
tempstr[0]:=#0;
IF fieldwidth-StrLen(strng) > 0 THEN
BEGIN
FillChar(tempstr[0],60,#0);
FillChar(tempstr[0],fieldwidth-StrLen(strng),' ');
END;
{ Now concatenate str to the end of tempstr, and
move the results back into strng so it can go home. }
StrCat(tempstr,strng);
StrCopy(strng,tempstr);
END; { RightJustifyString }
(************************************************************
** Fill out a string to n bytes. Pads on right with blanks.
** This routine will also truncate if necessary.
*)
PROCEDURE FillOutString( fieldwidth : Integer; strng: PChar ) ;
BEGIN
{ Attach fieldwidth-Length(string) blanks.
Don't bother if that's a negative number or zero. }
IF fieldwidth-StrLen(strng) > 0 THEN
FillChar(strng[StrLen(strng)],fieldwidth-StrLen(strng),' ');
strng[fieldwidth-1]:=#0;
END; { FillOutstring }
(*************************************************
** Display a line of test comparison information.
** This routine determines whether the current line is
** greater than the starting line, but less than the
** ending line. If so, the current line can be displayed.
** If not, then it simply updates the current line
** and returns without displaying anything.
** NOTE: This routine borrows the previously-defined
** routine DisplayBenchLine, which updates screen
** positions appropriately.
*)
PROCEDURE DispCompTestLine( testnum: Integer; VAR currentline: Integer );
VAR
lineotext: ARRAY[0..59] of Char; { Line to output }
tempstr: ARRAY[0..20] of Char; { A temp. string }
result: Real; { Value from file }
iterspersec: Real; { Iterations per second }
i: Integer; { Loop index }
BEGIN
{ Verify that the line we are about to display is in the
active portion of the window. }
IF (currentline>=bcBeginLine) AND (benchLineY<benchLineHDCheight) THEN
BEGIN
{ Get the test name }
StrPCopy(lineotext,test_name[testnum]);
FillOutString(18,lineotext);
{ Attach the iterations per second from the comparison system }
result:=fbptr^.testresult[testnum];
Str(result:10:2,tempstr);
RightJustifyString(10,tempstr);
StrCat(lineotext,tempstr);
{ If we have no values for this test yet, then the
rest of the line is ...well...blank. }
IF (iterarray[testnum]=0) OR (elapsedtsecarray[testnum]=0) THEN
StrCat(lineotext,' --test not run--')
ELSE
BEGIN
{ Calculate the iterations per second }
iterspersec:=iterarray[testnum];
iterspersec:=iterspersec * items_per_iter[testnum]*1000;
iterspersec:=iterspersec / elapsedtsecarray[testnum];
{ If the test is one of the file I/O tests, adjust for
K bytes per second }
IF (testnum=sfio_test_id) OR (testnum=rfio_test_id) THEN
iterspersec:=iterspersec / 1024;
Str(iterspersec:10:2,tempstr);
{ Attach iterations per second to the line already built }
StrCat(lineotext,' ');
RightJustifyString(10,tempstr);
StrCat(lineotext,tempstr);
{ Calculate the index }
result:=iterspersec / fbptr^.testresult[testnum];
Str(result:10:2,tempstr);
{ Attach the index }
StrCat(lineotext,' ');
RightJustifyString(8,tempstr);
StrCat(lineotext,tempstr);
END;
{ Display it }
DisplayBenchLine(lineotext,StrLen(lineotext));
END;
Inc(currentline); { Increment the current line }
END; { DispCompTestLine }
(*******************************************
** Display benchmark comparison information
** This is handled within a simple dialog box with a
** scroll bar and an EXIT button.
*)
FUNCTION BenchCompDialog(Dialog: HWnd; Message, WParam: Word ;
LParam: LongInt): Bool; export;
VAR
HDlgDC: HDC; { Device context }
systemname: ARRAY [0..70] of Char; { Name of system }
compdispline: ARRAY [0..80] of Char; { Display line string }
i: Integer; { Index }
j: Integer; { Another index }
currentline: Integer; { Current line on display }
DlgPntStruct: TPaintStruct; { Paint struct for dialog }
tempreal: Real; { Temporary real }
doInvalid: Bool; { Flag to invalidate rect }
syscoloridx: ARRAY [0..0] of Integer;
syscolorval: ARRAY [0..0] of Longint;
BEGIN
CASE Message OF
wm_InitDialog:
BEGIN
{ Grab the client rectangle area and place it into a global.
Decrement the bottom by a certain amount to allow
room for the button. We can use this for calculating the
number of displayable lines. }
GetClientRect(Dialog,bcDispRect);
bcDispRect.top:=bcDispRect.top+ansiffontheight;
bcDispRect.bottom:=bcDispRect.bottom-(2*ansiffontheight);
benchlineHDCheight:=bcDispRect.bottom-bcDispRect.top;
bcNumLines:=(benchlineHDCheight DIV sysfontheight)-2;
{ Get to the beginning of the file }
Reset(DataFile);
{ Read a bunch of data from the file until we've read it all }
i:=1;
REPEAT
{ Read in the system description. If it's first character is
an asterisk, we presume we've hit the end of the list
and we're done. }
READLN(DataFile,systemname);
IF systemname[0]<>'*' THEN
BEGIN
{ Allocate some memory for this guy }
fbhand[i]:=GlobalAlloc(GMEM_MOVEABLE OR GMEM_NODISCARD,SizeOf(CompData));
fbptr:=GlobalLock(fbhand[i]);
StrCopy(fbptr^.description,systemname);
{ Read in system name }
READLN(DataFile,systemname);
StrCopy(fbptr^.sysname,systemname);
{ Read in the test results. }
FOR j:= 1 TO max_test_id DO
BEGIN
READLN(DataFile,tempreal);
fbptr^.testresult[j]:=tempreal;
END;
{ Unlock this handle so the global heap can
compact if it needs to. }
GlobalUnlock(fbhand[i]);
Inc(i); { Advance to next handle }
END;
UNTIL systemname[0]='*';
bcNumSystems:=i-1; { # of systems in the table }
{ Calculate the total # of lines in the display. Use
this to set the range of the scrollbar. }
bcTotNumLines:= 2+bcNumSystems * (4+max_num_tests);
{ Set scrollbar range and initialize it }
SetScrollRange(Dialog,sb_VERT,1,bcTotNumLines,FALSE);
SetScrollPos(Dialog,sb_VERT,1,TRUE);
bcBeginLine:=1;
{ Set the focus }
SetFocus(GetDlgItem(Dialog,IDB_OK));
{ Initialize screen coordinate stuff to make the
DisplayBenchLine routine happy. }
BenchLineHDC := GetDC( Dialog );
BenchLineX := 10;
{ Set us up with a fixed pitch font }
SelectObject( BenchLineHDC, GetStockObject(ANSI_Fixed_Font) );
BenchLineY := ansiffontheight;
BenchLineYInc:= ansiffontheight;
{ Get old background color }
oldwinbkcolor:=GetSysColor(color_Window);
{ Set foreground and background colors }
syscoloridx[0]:=color_Window;
syscolorval[0]:=RGB(255,255,255);
SetSysColors(1,syscoloridx,syscolorval);
SetTextColor( BenchLineHDC, RGB(0,0,0) );
SetBkColor(BenchLineHDC,RGB(255,255,255));
SetBkMode(BenchLineHDC,Opaque);
END; { wm_InitDialog }
wm_VScroll:
BEGIN
doInvalid:=FALSE;
CASE WParam OF
{ NOTE: In the scrolling stuff, the variable bcBeginLine
indicates which line is at the top of the display
box. We calculate everything else based on bcBeginLine. }
sb_Top:
BEGIN
bcBeginLine:=1;
doInvalid:=TRUE;
END;
sb_Bottom:
BEGIN
bcBeginLine:=bcTotNumLines-1;
doInvalid:=TRUE;
END;
sb_LineUp:
BEGIN
IF bcBeginLine>1 THEN
bcBeginLine:=bcBeginLine-1;
doInvalid:=TRUE;
END;
sb_LineDown:
BEGIN
IF bcBeginLine<(bcTotNumLines-1) THEN
bcBeginLine:=bcBeginLine+1;
doInvalid:=TRUE;
END;
sb_PageUp:
BEGIN
bcBeginLine:=bcBeginLine-5;
IF bcBeginLine<1 THEN bcBeginLine:=1;
doInvalid:=TRUE;
END;
sb_PageDown:
BEGIN
bcBeginLine:=bcBeginLine+5;
IF bcBeginLine>(bcTotNumLines-1) THEN
bcBeginLine:=bcTotNumLines-1;
doInvalid:=TRUE;
END;
sb_ThumbPosition:
BEGIN
bcBeginLine:=WordRec(LParam).lo;
doInvalid:=TRUE;
END;
END; { CASE WParam }
SetScrollPos(Dialog,sb_VERT,bcBeginLine,TRUE);
IF doInvalid THEN
InvalidateRect(Dialog,@bcDispRect,TRUE);
END; { CASE wm_Vscroll }
wm_Paint:
BEGIN
{ Clear the display area }
HDlgDC:=BeginPaint(Dialog,DlgPntStruct);
{ Initialize the cursor position }
currentline:=1; { Start a line counter }
benchLineY:=sysfontheight;
i:=1; { i counts # of systems }
REPEAT
{ Lock the handle...resolving to pointer }
fbptr:=GlobalLock(fbhand[i]);
IF (currentline>=bcBeginLine) AND (benchLineY<benchLineHDCheight) THEN
DisplayBenchLine(fbptr^.description,StrLen(fbptr^.description));
{ See if the heading line is displayable. If so,
build it and display it. }
IF (currentline>=bcBeginLine) AND (benchLineY<benchLineHDCheight) THEN
BEGIN
StrCopy(compdispline,' Test ');
StrCopy(systemname,fbptr^.sysname);
FillOutString(18,systemname);
StrCat(compdispline,systemname);
StrCat(compdispline,' This System Index');
DisplayBenchLine(compdispline,StrLen(compdispline));
END;
Inc(currentline);
{ Display dashed line }
IF (currentline>=bcBeginLine) AND (benchLineY<benchLineHDCheight) THEN
DisplayBenchLine(dashstr,60);
Inc(currentline);
{ Display a line per test }
FOR j:=1 TO max_test_id DO
DispCompTestLine(j,currentline);
{ Display a blank line }
StrCopy(compdispline,' ');
DisplayBenchLine(compdispline,StrLen(compdispline));
{ Display complete for that system. Unlock the handle. }
GlobalUnlock(fbhand[i]);
Inc(i); { Increment system # }
UNTIL ((i-1)=bcNumSystems) OR (benchLineY>BenchLineHDCheight);
EndPaint(Dialog,DlgPntStruct);
END; { wm_Paint }
wm_Command:
BEGIN
CASE WParam OF
IDB_OK: { User pushed Exit button }
BEGIN
{ Get rid of all the handles we allocated. }
FOR i:=0 to (bcNumSystems-1) DO
BEGIN
GlobalUnlock(fbhand[i]);
GlobalFree(fbhand[i]);
END;
ReleaseDC(Dialog,BenchLineHDC);
EndDialog(Dialog,NULL);
BenchCompDialog:=TRUE;
syscolorval[0]:=oldwinbkcolor;
syscoloridx[0]:=color_Window;
SetSysColors(1,syscoloridx,syscolorval);
Exit;
END; { IDB_OK }
END; { CASE WParam }
END; { wm_Command }
END; { CASE Message }
BenchCompDialog:=FALSE;
END; { BenchCompDialog }
(******************************************************
** DiskSpaceAlert
** This procedure throws up the alert that tells the
** guy he doesn't have enough disk space to run the
** disk space test.
*)
PROCEDURE DiskSpaceAlert;
VAR
dlgproc: TFarProc; { Procedure instance }
BEGIN
ShowCursor(TRUE);
ADTx:=28;
ADTy:=20;
StrCopy(@AlertDlgText,'Disk tests require 6 MB of free disk space');
ADTCount:=StrLen(@AlertDlgText);
dlgproc:=MakeProcInstance(@StandardalertDialog,HInstance);
DialogBox(HInstance,'NOMEMDLG',HByteWin,dlgproc);
FreeProcInstance(dlgproc);
ShowCursor(FALSE);
END; { DiskSpaceAlert }
(*********************************************************
** Execute the benchmarks selected and record the results
** in the proper places.
*)
PROCEDURE DoTests;
VAR
i: Integer; { Loop index }
BEGIN
{ Turn the cursor off }
ShowCursor(FALSE);
FOR i := 1 TO max_num_tests DO
IF do_test_flags[i] THEN
BEGIN
CASE i OF
pixel_test_id:
BEGIN
PixelTest;
END;
line_test_id:
BEGIN
LineTest;
END;
rect_test_id:
BEGIN
RectTest;
END;
poly_test_id:
BEGIN
PolygonTest;
END;
arce_test_id:
BEGIN
EllipseTest;
END;
bitblt_test_id:
BEGIN
BitbltTest;
END;
lmem_test_id:
BEGIN
LMemTest;
END;
gmem_test_id:
BEGIN
GMemTest;
END;
sfio_test_id:
BEGIN
{ Make sure we have enough space }
IF DiskFree(0)<disk_space_needed THEN
DiskSpaceAlert
ELSE
sfile_io;
END;
rfio_test_id:
BEGIN
IF DiskFree(0)<disk_space_needed THEN
DiskSpaceAlert
ELSE
rfile_io( rfile_io_secs * 1000); {test works in milliseconds}
END;
texto_test_id:
BEGIN
TextTest;
END;
END; { CASE }
END; { FOR }
someTests := TRUE;
{ Turn cursor back on }
ShowCursor(TRUE);
END; { DoTests }
{ **************************** }
{ ** MENU HANDLING ROUTINES ** }
{ **************************** }
PROCEDURE MainMenuProc(WParam: WORD);
VAR
dlgproc: TFarProc; { Procedure instance }
BEGIN
CASE WParam OF
IDM_SETLOG: { ** Set Log File ** }
{ Display file dialog allowing user to select a log file }
BEGIN
dlgproc:=MakeProcInstance(@GetLogNameDialogAction,HInstance);
DialogBox(HInstance,'GETLOGDIALOG',HByteWin,dlgproc);
FreeProcInstance(dlgproc);
END;
IDM_DISPLOG: { ** Display Log File ** }
{ Display current log information }
BEGIN
if( someTests )
then begin
displayResults( TRUE, TRUE ); { show results on screen, write to file }
end;
END;
IDM_EXIT: { ** Exit the program ** }
BEGIN
SendMessage(HByteWin,wm_Close,0,0);
Exit;
END;
IDM_INFO: { ** About box ** }
BEGIN
ADTCount:=-1; { Alert dialog...display byte logo }
dlgproc:=MakeProcInstance(@StandardAlertDialog,HInstance);
DialogBox(HInstance,'ABOUTDLG',HByteWin,dlgproc);
FreeProcInstance(dlgproc);
END;
IDM_CONFBENCHES: { ** Configure benchmarks ** }
{ Fire up the dialog box for configuring benchmarks }
BEGIN
dlgproc:=MakeProcInstance(@BenchConfigDialog, HInstance);
DialogBox(HInstance,'BCONFDLG',HByteWin,dlgproc);
FreeProcInstance(dlgproc);
END;
IDM_COMPINFO: { ** Display comparison information ** }
BEGIN
{ We have to see if the comparison data file is available.
If so,we can go ahead and display that dialog box.
If not, throw up an alert dialog box. }
IF iscompfilethere THEN
BEGIN
dlgproc:=MakeProcInstance(@BenchCompDialog,HInstance);
DialogBox(HInstance,'BCMPDLG',HByteWin,dlgproc);
FreeProcInstance(dlgproc);
END
ELSE
BEGIN
ADTx:=28;
ADTy:=20;
StrCopy(@AlertDlgText,'Comparison Data File Not Found');
ADTCount:=StrLen(@AlertDlgText);
dlgproc:=MakeProcInstance(@StandardalertDialog,HInstance);
DialogBox(HInstance,'NOMEMDLG',HByteWin,dlgproc);
FreeProcInstance(dlgproc);
END;
END;
IDM_SYSCONF: { ** Display system configuration ** }
BEGIN
InitBenchDisplay;
logFileHeader( FALSE );
CloseBenchDisplay;
END;
IDM_SETDEFS: { ** Set to default configurations ** }
BEGIN
dlgproc:=MakeProcInstance(@SetToDefaultsDialog,HInstance);
DialogBox(HInstance,'SDEFDLG',HByteWin,dlgproc);
FreeProcInstance(dlgproc);
END;
IDM_EXECUTE: { ** Execute benchmarks ** }
BEGIN
DoTests; { Execute selected benchmarks }
DisplayResults( TRUE, FALSE ); { Display results }
END;
END; { CASE }
END; { MainMenuProc }
(*
** WINDOW HANDLING ROUTINES FOLLOW
*)
{ ********************************************}
{ WINDOW PROCEDURE FOR 'BYTEWB' WINDOW CLASS }
FUNCTION ByteWinProc(Window: HWnd; Message, WParam: Word;
LParam: Longint): Longint; export;
BEGIN
ByteWinProc:=0;
{ Handle incoming messages }
CASE Message OF
wm_Create:
BEGIN
END;
wm_Command:
BEGIN
MainMenuProc(WParam); { Handle menu stuff }
Exit;
END;
wm_Destroy:
BEGIN
PostQuitMessage(0);
Exit;
END;
END; { CASE }
{ If we fall through to here...pass it along }
ByteWinProc:=DefWindowProc(Window, Message, WParam, LParam);
END;
{ *********************************************** }
{ INITIALIZE FIRST INSTANCE }
{ Initialize the first instance of the program. }
{ 1. Register all windows classes. }
{ 2. Create any objects we will ultimately use. }
PROCEDURE InitFirstInstance;
VAR
ByteWinClass: TWndClass;
BEGIN
{ Ready our window class for registration }
ByteWinClass.style:=cs_HRedraw OR cs_VRedraw;
ByteWinClass.lpfnWndProc:=@ByteWinProc;
ByteWinClass.cbClsExtra:=0;
ByteWinClass.cbWndExtra:=0;
ByteWinClass.hInstance:=HInstance;
{ ** NOTE: We should define our own ICON -- 7/9 RG }
ByteWinClass.hIcon:=LoadIcon(HInstance,'WB1');
ByteWinClass.hCursor:=LoadCursor(0,idc_Arrow);
{ ** NOTE: We should define a different color -- 7/9 RG }
ByteWinClass.hbrBackground:=GetStockObject(Black_Brush);
{ ** NOTE: Need to define a menu for this class -- 7/9 RG }
ByteWinClass.lpszMenuName:='BYTEMENU';
ByteWinClass.lpszClassName:='BYTEWB';
{ ** NOTE: Must add better error handling -- 7/9 RG }
IF (NOT RegisterClass(ByteWinClass))
THEN Halt(255);
END; { InitFirstInstance }
{ ******************************* }
{ INITIALIZE ADDITIONAL INSTANCES }
PROCEDURE InitAddedInstance;
BEGIN
END;
{ ************************ }
{ INITIALIZE ALL INSTANCES }
PROCEDURE InitAllInstance;
BEGIN
{ Create a window }
HByteWin:=CreateWindow('BYTEWB','BYTE Windows Benchmarks',
ws_OverlappedWindow,
0,
0,
640,
480,
0,
0,
HInstance,
NIL);
ShowWindow(HByteWin, sw_Normal ); {sw_Maximize);}
UpdateWindow(HByteWin);
END;
{ ********************* }
{ MAIN WINDOW PROCEDURE }
PROCEDURE WinMain;
VAR
Message: TMsg; { Message }
BEGIN
{ Initialize things properly }
IF HPrevInst=0
THEN
InitFirstInstance
ELSE
InitAddedInstance;
InitAllInstance;
InitGlobals;
if( autoLogAndExit )
then begin
doTests;
DisplayResults( TRUE, FALSE );
Halt( 0 );
end;
{ Enter the main event loop }
WHILE GetMessage(Message,0,0,0) DO
BEGIN
TranslateMessage(Message);
DispatchMessage(Message);
END;
Halt(Message.wParam);
END;
{ Here's the ... believe it or not ... heart }
{ of the program. }
BEGIN
WinMain;
END.